mjansson / foundation_lib

Cross-platform public domain foundation library in C providing basic support data types and functions to write applications and games in a platform-independent fashion.
The Unlicense
301 stars 23 forks source link

Question: why use objectmap for refcount objects #27

Closed ChengCat closed 5 years ago

ChengCat commented 5 years ago

Thanks for this great library! As a game developer who also prefer C instead of C++, I extremely appreciate your work.

I have a question: why do you use objectmap as an indirection to manage reference counted objects, instead of manipulating object pointers directly (putting the counter inside the object struct intrusively)? I haven't seen this design before, and didn't find any information in this repository. Could you explain the rationale?

btw. I need that task_lib, and want to merge that library into foundation_lib. Will you accept the pull request?

mjansson commented 5 years ago

The idea is that you can manage any kind of object, not only those that follow a reference counted object layout contract.

Regarding task_lib, the idea there is that the libs should remain separate and task_lib depend on foundation_lib, to avoid this base library of growing into a kitchen sink.

ChengCat commented 5 years ago

Thanks for the explanation! That makes sense.

Regarding task_lib, I thought it is fundamental enough to be merged into foundation_lib, and it seems that you did the same with timer_lib. It is definitely acceptable to leave task_lib as a separate library though. :)

mjansson commented 5 years ago

Raw pointers with reference count in the target memory area also suffers from intrinsic thread unsafety. To check if the pointer is valid by looking at the reference count, you need to access the memory area, potentially causing a segfault if it has been freed.

With the object map and indirect "handles", you always increase reference when accessing the raw pointer through objectmap_acquire and you can be sure it is valid until you release the access with a call to objectmap_release, all in a thread safe way. The lifetime of the raw pointer becomes well defined.

ChengCat commented 5 years ago

Thanks for the further explanation!

To check if the pointer is valid by looking at the reference count, you need to access the memory area, potentially causing a segfault if it has been freed.

I don't think this is how reference counting usually works. A programmer should be sure that at least one reference count is acquired before doing any operation on the object, including checking the current reference count.

objectmap however makes weak references possible. All object_ts can be seen as weak references, and the number of strong references to the object (i.e. reference count) are manipulated explicitly with objectmap_acquire and objectmap_release. This is done at the expense of an indirect memory lookup. I'd say it's an interesting design, and has its trade-offs.

I have found foundation_lib to have some other interesting and unusual designs. For example, condition variable is merged into mutex, and each mutex has a string name. I'd definitely try them out in my game. :)

mjansson commented 5 years ago

Yes, a weak reference is basically what it is. I'll improve the documentation a bit regarding this.