mdbergmann / cl-gserver

Sento - Actor framework featuring actors and agents for easy access to state and asynchronous operations.

Home Page:https://mdbergmann.github.io/cl-gserver/index.html

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Some questions about atomic in cl-gserver

hxzrx opened this issue · comments

Hi,

As I checked some codes of cl-gserver, there're several files use atomic operation.

  1. atomic.lisp, which defines atomic-cas, in this method definition, (when cas-result (setf ....) is really redundant, cas can make sure it's been set if cas succeeds. Furthermore, the setf after cas may be dangerous, this is usually a trap and is hard to debug.
  2. router.lisp, which defines make-round-robin-strategy, this function returns a lambda which always returns the new value, however, the cas operation may fail and leave the atomic-integer not changed, this might make the returned value not what you want.
  3. actor-context.lisp, in the definition of %add-actor, cas can make sure that a new actor will be successfully added in a loop. And finally, in the definition of %remove-actor, a single cas can not make sure it's removed successfully without a loop.

Since I just grepped the lisp file with atomic, and you may have some codes in other files which make sure all these are OK. But if you can confirm that these functions should get enhancement, I'm glad to make a patch.

Hi.
Those are valid points.

For 1., are you sure the cas operation sets the value to the place (slot-value ref 'cell) even though a dynamic variable is used?

Generally there are no formal proves that the cas operations are OK. They are 'only' empirically tested. But this is of course not exhaustive.

So yes, please make a patch.

I would think though that using cas should be as simple as possible and the nitty-gritty bits should be abstracted away.
So, i.e. the functions %add-actor, %remove-actor preferably don't deal with loops.

Hi. Those are valid points.

For 1., are you sure the cas operation sets the value to the place (slot-value ref 'cell) even though a dynamic variable is used?

Generally there are no formal proves that the cas operations are OK. They are 'only' empirically tested. But this is of course not exhaustive.

So yes, please make a patch.

Yes, for dynamic variables. cas is rather low level, in fact, it will expand to the actual place of the lower level swap object of the higher level variable, so, it's only depends on what the actual object the variable currently binds to.

I would think though that using cas should be as simple as possible and the nitty-gritty bits should be abstracted away. So, i.e. the functions %add-actor, %remove-actor preferably don't deal with loops.

I believe so, atomic operations in %add-actor, %remove-actor just do something like enqueue or dequeue, %add-actor and %remove-actor themselves should keep simple. Furthermore, either add-actor or remove-actor will hardly be the bottleneck, using a lock will make the code more concise, I think, but this is another style.

For this issue, I will make an PR for make-round-robin-strategy and atomic-cas as soon as possible.

Furthermore, either add-actor or remove-actor will hardly be the bottleneck, using a lock will make the code more concise, I think, but this is another style.

I wouldn't care if locks are used, however not directly in actor-context package. If you'd wrap an array in a separate package and put locking code around it, like a 'concurrent-array' primitive, that would be fine as well.
Maybe there is something out there already.

Before I create a PR for atomic-cas, I must make sure how the special variable *the-ref* is designed.

The special variables cas's logic is different from that directly using the cas-place such as (slot-value ref 'cell).
In the definition of atomic-cas, *the-ref* binds to the VALUE of the value of the cell slot first. In ccl, for example, conditional-store will invoke ccl::%symbol-binding-address with the symbol of *the-ref* to get the address, which has nothing to do with the original cell place, and thus the cell's value will not be modified. That's why you have to setf the slot value when cas succeeds.

Since *the-ref* is only used in atomic.lisp, I don't know if it's Ok if I remove this special variable and directly use the cell's place in atomic-cas.

It's ok to remove it if not really needed, considering the 'atomics' cas works consistently across the implementations.

Can this be closed with the PR?

Can this be closed with the PR?

Yeah, please close this.