mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 10:28:10 +00:00
LibCore: Make CObject reference-counted
Okay, I've spent a whole day on this now, and it finally kinda works! With this patch, CObject and all of its derived classes are reference counted instead of tree-owned. The previous, Qt-like model was nice and familiar, but ultimately also outdated and difficult to reason about. CObject-derived types should now be stored in RefPtr/NonnullRefPtr and each class can be constructed using the forwarding construct() helper: auto widget = GWidget::construct(parent_widget); Note that construct() simply forwards all arguments to an existing constructor. It is inserted into each class by the C_OBJECT macro, see CObject.h to understand how that works. CObject::delete_later() disappears in this patch, as there is no longer a single logical owner of a CObject.
This commit is contained in:
parent
0c72e0c09f
commit
bc319d9e88
45 changed files with 174 additions and 233 deletions
|
@ -20,7 +20,7 @@
|
|||
#include <sys/uio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
HashMap<int, WSClientConnection*>* s_connections;
|
||||
HashMap<int, NonnullRefPtr<WSClientConnection>>* s_connections;
|
||||
|
||||
void WSClientConnection::for_each_client(Function<void(WSClientConnection&)> callback)
|
||||
{
|
||||
|
@ -38,24 +38,20 @@ WSClientConnection* WSClientConnection::from_client_id(int client_id)
|
|||
auto it = s_connections->find(client_id);
|
||||
if (it == s_connections->end())
|
||||
return nullptr;
|
||||
return (*it).value;
|
||||
return (*it).value.ptr();
|
||||
}
|
||||
|
||||
WSClientConnection::WSClientConnection(CLocalSocket& client_socket, int client_id)
|
||||
: Connection(client_socket, client_id)
|
||||
{
|
||||
if (!s_connections)
|
||||
s_connections = new HashMap<int, WSClientConnection*>;
|
||||
s_connections->set(client_id, this);
|
||||
s_connections = new HashMap<int, NonnullRefPtr<WSClientConnection>>;
|
||||
s_connections->set(client_id, *this);
|
||||
}
|
||||
|
||||
WSClientConnection::~WSClientConnection()
|
||||
{
|
||||
// NOTE: Move the windows out of 'm_windows' before teardown. This prevents code
|
||||
// that runs in response to window destruction from trying to iterate over
|
||||
// a partially destroyed window list.
|
||||
auto windows = move(m_windows);
|
||||
s_connections->remove(client_id());
|
||||
}
|
||||
|
||||
void WSClientConnection::send_greeting()
|
||||
|
@ -68,6 +64,11 @@ void WSClientConnection::send_greeting()
|
|||
post_message(message);
|
||||
}
|
||||
|
||||
void WSClientConnection::die()
|
||||
{
|
||||
s_connections->remove(client_id());
|
||||
}
|
||||
|
||||
void WSClientConnection::post_error(const String& error_message)
|
||||
{
|
||||
dbgprintf("WSClientConnection::post_error: client_id=%d: %s\n", client_id(), error_message.characters());
|
||||
|
@ -370,7 +371,7 @@ void WSClientConnection::handle_request(const WSAPIDestroyMenubarRequest& reques
|
|||
void WSClientConnection::handle_request(const WSAPICreateMenuRequest& request)
|
||||
{
|
||||
int menu_id = m_next_menu_id++;
|
||||
auto menu = make<WSMenu>(this, menu_id, request.text());
|
||||
auto menu = WSMenu::construct(this, menu_id, request.text());
|
||||
m_menus.set(menu_id, move(menu));
|
||||
WSAPI_ServerMessage response;
|
||||
response.type = WSAPI_ServerMessage::Type::DidCreateMenu;
|
||||
|
@ -389,6 +390,7 @@ void WSClientConnection::handle_request(const WSAPIDestroyMenuRequest& request)
|
|||
auto& menu = *(*it).value;
|
||||
WSWindowManager::the().close_menu(menu);
|
||||
m_menus.remove(it);
|
||||
remove_child(menu);
|
||||
WSAPI_ServerMessage response;
|
||||
response.type = WSAPI_ServerMessage::Type::DidDestroyMenu;
|
||||
response.menu.menu_id = menu_id;
|
||||
|
@ -738,7 +740,7 @@ void WSClientConnection::handle_request(const WSAPIGetClipboardContentsRequest&)
|
|||
void WSClientConnection::handle_request(const WSAPICreateWindowRequest& request)
|
||||
{
|
||||
int window_id = m_next_window_id++;
|
||||
auto window = make<WSWindow>(*this, request.window_type(), window_id, request.is_modal(), request.is_resizable(), request.is_fullscreen());
|
||||
auto window = WSWindow::construct(*this, request.window_type(), window_id, request.is_modal(), request.is_resizable(), request.is_fullscreen());
|
||||
window->set_background_color(request.background_color());
|
||||
window->set_has_alpha_channel(request.has_alpha_channel());
|
||||
window->set_title(request.title());
|
||||
|
@ -766,11 +768,15 @@ void WSClientConnection::handle_request(const WSAPIDestroyWindowRequest& request
|
|||
}
|
||||
auto& window = *(*it).value;
|
||||
WSWindowManager::the().invalidate(window);
|
||||
m_windows.remove(it);
|
||||
WSAPI_ServerMessage response;
|
||||
response.type = WSAPI_ServerMessage::Type::DidDestroyWindow;
|
||||
response.window_id = window.window_id();
|
||||
post_message(response);
|
||||
|
||||
dbg() << *this << " removing window child " << window << " refs: " << window.ref_count() << " parent: " << window.parent();
|
||||
remove_child(window);
|
||||
ASSERT(it->value.ptr() == &window);
|
||||
m_windows.remove(window_id);
|
||||
}
|
||||
|
||||
void WSClientConnection::post_paint_message(WSWindow& window)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue