Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SEMAPHORE-COUNT #70

Open
phoe opened this issue May 10, 2020 · 6 comments
Open

Add SEMAPHORE-COUNT #70

phoe opened this issue May 10, 2020 · 6 comments

Comments

@phoe
Copy link
Contributor

phoe commented May 10, 2020

In the Lisp Koans, we have a threading koan that, when solved, is supposed to look similar to the following:

(defvar *semaphore* (bt:make-semaphore))

(defun signal-our-semaphore ()
  (bt:signal-semaphore *semaphore*))

(defun wait-on-our-semaphore ()
  (bt:wait-on-semaphore *semaphore* :timeout 0.1))

(define-test semaphore
  (bt:join-thread (bt:make-thread #'signal-our-semaphore))
  (bt:join-thread (bt:make-thread #'signal-our-semaphore))
  (bt:join-thread (bt:make-thread #'signal-our-semaphore))
  (assert-equal 2 (bt:join-thread (bt:make-thread #'wait-on-our-semaphore)))
  (assert-equal 1 (bt:join-thread (bt:make-thread #'wait-on-our-semaphore)))
  (assert-equal 0 (bt:join-thread (bt:make-thread #'wait-on-our-semaphore)))
  (assert-equal nil (bt:join-thread (bt:make-thread #'wait-on-our-semaphore)))
  (assert-equal nil (bt:join-thread (bt:make-thread #'wait-on-our-semaphore))))

The previous version of koan also had semaphore-count calls to assert the correct behaviour of the threading system. It looked similar to the following:

(define-test semaphore
  (assert-equal 0 (sb-thread:semaphore-count *semaphore*))
  (bt:join-thread (bt:make-thread #'signal-our-semaphore))
  (assert-equal 1 (sb-thread:semaphore-count *semaphore*))
  (bt:join-thread (bt:make-thread #'signal-our-semaphore))
  (bt:join-thread (bt:make-thread #'signal-our-semaphore))
  (assert-equal 3 (sb-thread:semaphore-count *semaphore*))
  (assert-equal 2 (bt:join-thread (bt:make-thread #'wait-on-our-semaphore)))
  (assert-equal 1 (bt:join-thread (bt:make-thread #'wait-on-our-semaphore)))
  (assert-equal 1 (sb-thread:semaphore-count *semaphore*))
  (assert-equal 0 (bt:join-thread (bt:make-thread #'wait-on-our-semaphore)))
  (assert-equal 0 (sb-thread:semaphore-count *semaphore*))
  (assert-equal nil (bt:join-thread (bt:make-thread #'wait-on-our-semaphore)))
  (assert-equal 0 (sb-thread:semaphore-count *semaphore*)))

The obvious missing thing is the lack of bt:semaphore-count in Bordeaux Threads. The Lisp Koans rolled out its own semaphore object based on the bordeaux-threads provided one to work around this issue, which I have removed in google/lisp-koans#111 to clean up the code.


A comment from @Slids at Clozure/ccl#308 says:

Stellian doesn't want a semaphore-count function, already asked.
Arguably it's not very informative, the count could change immediately after or
before retrieved and and since it's a condition variable you have no great
use of it for a CAS utility...

I agree that such a function is nigh useless in actual production code, since the simple act of returning a semaphore value causes it to immediately become stale. Therefore depending on the value of this function in multithreaded code single-handedly enables race conditions to happen.

At the same time, the Lisp Koans have come up with, IMO, a somewhat surprising valid use case for that function - which is, introspecting the semaphore state in a controlled, single-threaded unit test case, where the semaphore is only available to the thread executing the test case. (The Koans spawn other threads via bt:make-thread and then wait for them to bt:join-thread, which is single-threaded enough, since the spawning thread is effectively paused at the time.) I imagine that other unit tests that single-threadedly run chunks of a multithreaded code to verify its functioning might also want to benefit from numeric assertions on the semaphore count during any given moment in the test execution.

Technically speaking, SBCL exports a function for accessing the count of a semaphore, the not-yet-merged ECL 20.4.24 semaphores also export one; it is also trivial to extract it from the current portable implementation that BT has for other CL implementations. The only missing implementation is CCL with a ticket at Clozure/ccl#308, but it seems that adding a ccl:semaphore-count that works similarly should be easy and therefore wouldn't be a blocker for adding this function to BT. Therefore, I think it can be said that there is a semaphore-count API that a portability library can wrap over.

Therefore, my question is: since, IMO, a valid use case for it has appeared, would you consider adding BT:SEMAPHORE-COUNT with the aforementioned warning for people who dare use it in production code?

@sionescu
Copy link
Owner

See Clozure/ccl#308 (comment).

@phoe
Copy link
Contributor Author

phoe commented Jun 13, 2020

OK - thanks for the reply. We'll implement the semaphore count function in CCL; it should be available in the next CCL release.

@sionescu sionescu added the apiv2 label Jun 14, 2020
@sionescu sionescu changed the title Maybe-add SEMAPHORE-COUNT Implement SEMAPHORE-COUNT Jul 20, 2020
@sionescu sionescu changed the title Implement SEMAPHORE-COUNT Add SEMAPHORE-COUNT Jul 20, 2020
@sionescu
Copy link
Owner

When is the next release going to happen ?

@phoe
Copy link
Contributor Author

phoe commented Jul 22, 2020

I don't know about the release itself, but I still have not implemented this part; sorry, and thank you for the reminder.

@sionescu
Copy link
Owner

Any updates ?

@phoe
Copy link
Contributor Author

phoe commented Feb 28, 2021

I completely forgot about this issue and I do not have any progress in this matter or the related CCL ticket.

stewart123579 added a commit to stewart123579/lisp-koans that referenced this issue Dec 23, 2021
bordeaux-threads doesn't have count of threads functionality.

See:
    sionescu/bordeaux-threads#70
    google#111
@sionescu sionescu added this to the APIv2 GA milestone Jan 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants