void PushWeakObject(duk_context* ctx, Object* object)
{
    if (!object)
    {
        duk_push_null(ctx);
        return;
    }

    duk_push_heap_stash(ctx);

    // Check if the wrapper for the object already exists in stash
    // This is required so that comparisons of object references (e.g. against the me property) work properly
    if (duk_has_prop_index(ctx, -1, (size_t)object))
    {
        duk_get_prop_index(ctx, -1, (size_t)object);
        WeakPtr<Object>* oldPtr = GetWeakPtr(ctx, -1);
        if (oldPtr && oldPtr->Get() == object)
        {
            duk_remove(ctx, -2); // Remove stash
            return;
        }
        else
            duk_pop(ctx); // Valid existing wrapper not found
    }

    duk_push_object(ctx);
    WeakPtr<Object>* ptr = new WeakPtr<Object>(object);
    duk_push_pointer(ctx, ptr);
    duk_put_prop_string(ctx, -2, "\xff""weak");
    duk_push_c_function(ctx, WeakPtr_Finalizer, 1);
    duk_set_finalizer(ctx, -2);

    // Set prototype. If not found, use base class prototype (e.g. IComponent)
    duk_get_global_string(ctx, object->GetTypeName().CString());
    if (!duk_is_object(ctx, -1))
    {
        duk_pop(ctx);
        duk_get_global_string(ctx, object->GetTypeInfo()->GetBaseTypeInfo()->GetTypeName().CString());
    }
    duk_get_prop_string(ctx, -1, "prototype");
    duk_set_prototype(ctx, -3);
    duk_pop(ctx);

    // Proxied property access handling for scene, entity & component
    if (object->GetType() == Scene::GetTypeStatic())
        SetupProxy(ctx, SceneProxyFunctions);
    if (object->GetType() == Entity::GetTypeStatic())
        SetupProxy(ctx, EntityProxyFunctions);
    else if (dynamic_cast<IComponent*>(object))
        SetupProxy(ctx, ComponentProxyFunctions);

    // Store to stash
    duk_dup(ctx, -1);
    duk_put_prop_index(ctx, -3, (size_t)object);
    duk_remove(ctx, -2); // Remove stash
}
duk_ret_t WeakPtr_Finalizer(duk_context* ctx)
{
    WeakPtr<Object>* ptr = GetWeakPtr(ctx, 0);
    if (ptr)
    {
        delete ptr;
        duk_push_pointer(ctx, nullptr);
        duk_put_prop_string(ctx, 0, "\xff""weak");
    }
    return 0;
}
Example #3
0
void TcpListener::OnAcceptCallabck( evconnlistener* listener,
    evutil_socket_t fd, sockaddr* addr, int socklen )
{
    struct event_base *base = evconnlistener_get_base(listener_);
    struct bufferevent *bev = bufferevent_socket_new(base, fd,
        BEV_OPT_CLOSE_ON_FREE | BEV_OPT_THREADSAFE | 
        BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS);

    std::shared_ptr<TcpClient> client(new TcpClient(bev, GetWeakPtr()));

    clients_.push_back(client);
    if (acceptCallback_)
    {
        acceptCallback_(client);
    }
    
}