1
Fork 0
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:
Andreas Kling 2019-09-22 00:17:53 +02:00
parent 0c72e0c09f
commit bc319d9e88
45 changed files with 174 additions and 233 deletions

View file

@ -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)