CoreLinux++ should provide an Event semaphore. An event semaphore is a semaphore which can be blocked on until the target event occurs which releases all blocking threads.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
frankc wrote:
> CoreLinux++ should provide an Event semaphore. An event semaphore is a semaphore
> which can be blocked on until the target event occurs which releases all blocking threads.
What about the non-broadcast signal (e.g., target event) that only releases the first blocked thread in the queue? (pthread_cond_signal vs. pthread_cond_broadcast)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
not an use case but a requirement, that being efficiency:
take for example a command queue that is being asynchronously updated by multiple threads and you have multiple threads pulling off of this queue and processing the commands/directives. say, at a certain point in time the queue is empty, this means all command processing threads are in a wait mode. say now that one command is pushed onto the queue. if the push generates a broadcast (ala, pthread_cond_broadcast semantics) this will wake up every waiting thread and they will all contend for the resource, in this case the queue mutex semaphore, and the winner will go onto process the command while the losers will go back to waiting. whereas if the push generated a signal (ala, pthread_cond_signal) only the next thread in line would be woken up and all the others would still be waiting.
in this situation, ultimately the results are the same: one thread acquires the queue semaphore lock and processes the command while the others end up waiting. but which scenario took more execution cycles to get to the same outcome?
this is the kind of example illustrated in _Programming with Posix Threads_ by Butenhoff (sp?).
also, if i remember correctly most multi-threading sources on the topic of event semaphore signalling say that if you can you should use the signal methodology instead of broadcast. i'll try to find a referential passage in a couple of my books to support this claim.
a good case for the command queue processing threads to use broadcast semantics is when not all the processing threads have the same thread priority--in this case you WANT the threads to contend for resources that way the higher priority thread(s) is/are honored.
on the other hand, when all the processing threads have the same thread priority it makes more sense to use signal semantics and use the time that would be spent on resource contention elsewhere.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
hmm, it seems in my previous post i was talking about my opinionated take on what the experts recommend. here's what Butenhof (Programming with POXIS Threads, Addison Wesley 1997) has to say:
on page 81, paragraph 4:
<excerpt>
It is easy to think of "broadcast" as a generalization of "signal," but it is more accurate to think of signal as an optimization of broadcast. Remember that it is never wrong to use broadcast instead of signal since waiters have to account for intercepted and spurious wakes. The only difference, in fact, is efficiency: A broadcast will wake additional threads that will have to test their predicate and resume waiting. But, in general, you can't replace a broadcast with a signal. "When in doubt, broadcast."
Use signal when only one thread needs to wake up to process the changed state, and when <i>any</i> waiting thread can do so. ....
If you add a single item to a queue, and only threads waiting for an item to appear are blocked on the condition variable, then you should probably use a signal. That'll wake up a single thread to check the queue and let the others sleep undisturbed, avoiding unnecessary context switches. On the other hand, if you add more than one item to the queue, you will probably need to broadcast.
</excerpt>
This is from the man who wrote Digital UNIX's multi-threading facilities.
Does this meet the need for a valid use case describing the need for signal AND broadcast semantics/functionality?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
So what I read are requirements for (and I am adding my own at this point):
1. A "broadcast" event - which doesn't care what priorities the waiting threads have (in some OS implementations, the thread with the highest priorit(y | ies) will be "signalled" first).
2. A priority based queue where only the front thread of the queue is signalled when the "event" triggers.
3. A priority based queue where each thread in the queue gets triggered sequentially.
4. Both 2 & 3 with no regard to priority.
In these cases, are the priorities based on thread priorities or some arbitrary type we provide?
The valid use case was for my understanding of your context. I appreciate it all.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
#1 -- the underlying scheduler will take care of which thread actually wins the contention. for our purposes it is explicit enough to say broadcast will wake up all threads waiting on the event.
#2 -- again, the underlying scheduler will take care of which thread is actually signalled. it is explicit enough for our purposes to say a signal will wake up one and only one thread waiting on the event.
to answer your priorities question: when i speak of thread priority i'm thinking of the priority requested for the thread at creation time.
(this mechanism is roughly equivalent in almost all environments from java, to the unices even to win32)
i think specifying which waiters get woken up etc will only be important if we do decide to write our own userland scheduler. and if so these things and others should be captured as part of the scheduler's requirements.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hmm, I thought of something in my car on the way to work this morning concerning the latest proposition(s) for the event semaphore(s).
It amounts to this: I'm not so sure breaking the event semaphore into two distinct types would be as beneficial as instead incorporating the "broadcast" and "signal" semantics into 2 separate methods. A quick and valid use case scenario for this is:
We have multiple threads, as before, waiting on a queue to process commands pushed onto it. This queue is non-standard in that it has a batch push method (where you can push multiple commands onto the queue with one operation) as well as the expected standard push that places one command on the queue. Waking up threads in the latter instance is an easy consideration; we have one command so wake up merely one thread. In the former case, however, we need to consider the nature of desired command execution. If we have multiple threads to process commands (and for the sake of simplicity in this example) it makes sense that concurrent execution is expected. So in the case of a batch push we would want to broadcast to wake up all waiters and let them plow through the queue.
Another use case: we have a simple command queue (no batch push method) with multiple command processing threads that utilizes only a selective or signal event. What happens when it is time to shutdown? Sure we can call exit() or pthread_cancel() to stop the blocking threads from further execution--but we shouldn't make it a requirement. Instead, we should be able to set a thread-specific variable for each processing thread that tells them its time to shutdown (or set a global read only shutdown boolean) and then broadcast for them to wake up and move on, which in this case would be to clean up and terminate. But this option isn't available to use as we chose for efficiency to use the signal event. Out only recorse would be to cycle through a loop as many times as we have processing threads (assuming we KNOW how many we have) and wake up each one individually.
Granted all of my arguments above can be mitigated by tricky and complex coding (though waiting on multiple events is not a trivial coding task) but if the same end can be acheived with more simple code why not keep it simple?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
To your first point, I am not making any implementation decisions here, just pointing out a requirement of behavior.
In your first use case I would submit that the choice of Broadcast versus Selective is the implementors choice that best fits their intent.
To the second use case, I have implemented in the past, and we are getting into specific problem space here (not a bad thing, just a thing), is a shutdown message is put on the queue. The broadcast wakes up the thread implementation and it detects the shutdown request and "poof", where the main thread (application) needs to block exiting until the threads are gone. No globals, no need for the queue to know the thread interface, no forcing of state into all derivations, etc.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
seems i got my panties in a premature bunch. i lost sight of the fact that your are specifying INTERFACE requirements. this allows for an event semaphore to implement both the selective and broadcast event interfaces.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
> seems i got my panties in a premature bunch.
> i lost sight of the fact that your are
> specifying INTERFACE requirements. this
> allows for an event semaphore to implement
> both the selective and broadcast event
> interfaces.
As much as I would like to get to the
implementation, I think it would do diservice
to the process. The Signal requirements are
shaping up to where it is recognized that there
are two different specifications, each
providing seperate behavior. Following the
process we see that, from a analysis standpoint,
it would possibly be modeled as:
EventSemaphore---- isA ----> Semaphore
BroadcastSemaphore -- isA -->EventSemaphore
or the addition of
QueuedEventSemaphore-- isA -->EventSemaphore
And that is fine for analysis, you could even bring it to the design. Now in the design and thinking of implementation we consider scale, performance, derivations, etc. we may make a
decision that there is only EventSemaphore with
State determining what mode it operates in.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
seems i got my panties in a premature bunch. i lost sight of the fact that your are specifying INTERFACE requirements. this allows for an event semaphore to implement both the selective and broadcast event interfaces.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
CoreLinux++ Semaphore Requirement (1589) Draft - Version 0.1
A Semaphore is a protocol by which processes and/or threads agree to follow for the purpose of controlled access to a resource. The resource can be anything that the developer considers to need access controls on, such as memory, hardware, methods, computer instructions, and so on.
The protocol is pinned to the kernel which enforces blocking (being made to wait) the caller until a resource is available.
Callers can elect to avoid being put into a blocked state and return immediatley without control to the resource. Callers may also request that they are put into a blocked state for a specified amount of time. If, at the end of the specified time, the request has not been satisified, it is returned with a Timeout indicator.
The owner or creator of the semaphore can elect to enforce balking behavior on a Semaphore. When so designated, the Semaphore can turn back any request until some condition in their solution space is met regardless of the callers blocking options. If a caller access attempt is balked, is it returned with a Balked indicator.
Used to serialized access to a resource (one to one)
----------------------------------------------------
When used to prevent concurrent access to a resource, the caller must first obtain control of the associated Semaphore. When a caller has control of the Semaphore, the resource(s) that are associated with the Semaphore are considered locked and accessible by the caller. When the caller has completed access of the resource it relinquishes control and the resource is now considered unlocked.
Attempts may be made to access the resource by other threads of execution or from seperate processes. These callers are queued and the requestor is put into a blocked state. In this state the caller waits until the resource is unlocked. If multiple requests are blocking for the same control, the determination of which caller gains access next is, from a applications perspective, arbitrary.
When balking mode is enabled callers will be turned away as long as the Semaphore is locked.
Used to provide concurrent finite access (one to many)
------------------------------------------------------
When used in this fashion, a Semaphore can be used as an access count controller. The Semaphore is created, as determined by the solution domain, with the maximum number of concurrent active callers allowed. As long as the caller count does not reach the maximum, the arrival will be granted immediate access. When the maximum has been reached, arriving callers are blocked.
When balking mode is enabled callers will be turned away until the count reduces to less than maximum.
Used to block callers until an event occurs (many to one)
---------------------------------------------------------
When used in this fashion, a single Semaphore is used to let callers block until some event occurs. Unlike the serialzed access, where one caller at a time is released to gain access to a resource, when the designated event occurs all blocked callers are released at once.
Balking mode is not available with this type Semaphore.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
CoreLinux++ Semaphore Requirement (1589) Draft - Version 0.2
A Semaphore is a protocol by which processes and/or threads agree to follow for the purpose of controlled access to a resource. The resource can be anything that the developer considers to need access controls on, such as memory, hardware, methods, computer instructions, and so on.
The protocol is pinned to the kernel which enforces blocking (being made to wait) the caller until a resource is available.
Callers can elect to avoid being put into a blocked state and return immediatley without control to the resource. Callers may also request that they are put into a blocked state for a specified amount of time. If, at the end of the specified time, the request has not been satisified, it is returned with a Timeout indicator.
The owner or creator of the semaphore can elect to enforce balking behavior on a Semaphore. When so designated, the Semaphore can turn back any request until some condition in their solution space is met regardless of the callers blocking options. If a caller access attempt is balked, is it returned with a Balked indicator.
Used to serialized access to a resource (one to one)
----------------------------------------------------
When used to prevent concurrent access to a resource, the caller must first obtain control of the associated Semaphore. When a caller has control of the Semaphore, the resource(s) that are associated with the Semaphore are considered locked and accessible by the caller. When the caller has completed access of the resource it relinquishes control and the resource is now considered unlocked.
Attempts may be made to access the resource by other threads of execution or from seperate processes. These callers are queued and the requestor is put into a blocked state. In this state the caller waits until the resource is unlocked. If multiple requests are blocking for the same control, the determination of which caller gains access next is, from a applications perspective, arbitrary.
When balking mode is enabled callers will be turned away as long as the Semaphore is locked.
Used to provide concurrent finite access (one to many)
------------------------------------------------------
When used in this fashion, a Semaphore can be used as an access count controller. The Semaphore is created, as determined by the solution domain, with the maximum number of concurrent active callers allowed. As long as the caller count does not reach the maximum, the arrival will be granted immediate access. When the maximum has been reached, arriving callers are blocked.
When balking mode is enabled callers will be turned away until the count reduces to less than maximum.
Used to block callers until an event occurs (many to one)
---------------------------------------------------------
When used in this fashion, a single Semaphore is used to let callers block until some event occurs. Unlike the serialzed access, where one caller at a time is released to gain access to a resource, when the designated event occurs all blocked callers are released at once.
The creator of this type of Semaphore can designate the maximum number of listeners that can wait on a single Semaphore event. When used in this manner, balking mode is automatically enabled.
When balking mode is enabled callers will be turned away until the number of listeners on the event drops below maximum.
CoreLinux Semaphore Functional Requirements
General Reqquirements
---------------------
There will be no restriction on the type of the Semaphore that can be created other than system dependent resources.In this event, an exception will be thrown indicating, if possible, why the Semaphore could not be created.
The default mode for all Semaphore will be non-Balking.
All Semaphores will support access by only the process that creates it.
All Semaphores will support access by the process that creates it, and any children that the process spawns.
All Semaphores will support access by any process.
All Semaphores will support read only operations for each of the above access modes.
All Semaphores will support read/write operations for each of the above access modes.
All Semaphores will support a recursion disposition.
All other Semaphores will support a lock semantic in that the caller will wait until the lock is obtained.
All Semaphores will support the lock semantic with no-wait option so that the caller will return immediatley if the lock can not be immediatley obtained.
All Semaphores will support the lock semantic with timeout option so that the caller can indicate a maximum amount of time before giving up trying to obtain the lock.
General One-to-One Semaphore
----------------------------
One-to-One Semaphores will support a create and automatically lock capability.
One-to-One Semaphores will support a create and no-lock capability.
General One-to-Many Semaphore
-----------------------------
One-to-Many Semaphores will support a create with a maximum resource count.
One-to-Many Semaphores will support a create and automatically lock capability which means no resources are available.
One-to-Many Semaphores will support a create and no-lock capability which means all (maximum) resources are available.
One-to-Many Semaphores will support increasing the maximum count from the managing process only.
General Many-to-One Semaphore
-----------------------------
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
CoreLinux++ Semaphore Requirement (1589) Draft - Version 0.3
A Semaphore is a protocol by which processes and/or threads agree to follow for the purpose of controlled access to a resource. The resource can be anything that the developer considers to need access controls on, such as memory, hardware, methods, computer instructions, and so on.
The protocol is pinned to the kernel which enforces blocking (being made to wait) the caller until a resource is available.
Callers can elect to avoid being put into a blocked state and return immediatley without control to the resource. Callers may also request that they are put into a blocked state for a specified amount of time. If, at the end of the specified time, the request has not been satisified, it is returned with a Timeout indicator.
The owner or creator of the semaphore can elect to enforce balking behavior on a Semaphore. When so designated, the Semaphore can turn back any request until some condition in their solution space is met regardless of the callers blocking options. If a caller access attempt is balked, is it returned with a Balked indicator.
Used to serialized access to a resource (one to one)
----------------------------------------------------
When used to prevent concurrent access to a resource, the caller must first obtain control of the associated Semaphore. When a caller has control of the Semaphore, the resource(s) that are associated with the Semaphore are considered locked and accessible by the caller. When the caller has completed access of the resource it relinquishes control and the resource is now considered unlocked.
Attempts may be made to access the resource by other threads of execution or from seperate processes. These callers are queued and the requestor is put into a blocked state. In this state the caller waits until the resource is unlocked. If multiple requests are blocking for the same control, the determination of which caller gains access next is, from a applications perspective, arbitrary.
When balking mode is enabled callers will be turned away as long as the Semaphore is locked.
Used to provide concurrent finite access (one to many)
------------------------------------------------------
When used in this fashion, a Semaphore can be used as an access count controller. The Semaphore is created, as determined by the solution domain, with the maximum number of concurrent active callers allowed. As long as the caller count does not reach the maximum, the arrival will be granted immediate access. When the maximum has been reached, arriving callers are blocked.
When balking mode is enabled callers will be turned away until the count reduces to less than maximum.
Used to block callers until an event occurs (many to one)
---------------------------------------------------------
When used in this fashion, a single Semaphore is used to let callers block until some event occurs. Unlike the serialzed access, where one caller at a time is released to gain access to a resource, when the designated event occurs all blocked callers are released at once.
The creator of this type of Semaphore can designate the maximum number of listeners that can wait on a single Semaphore event. When used in this manner, balking mode is automatically enabled.
When balking mode is enabled callers will be turned away until the number of listeners on the event drops below maximum.
Semaphore Groups
----------------
A Semaphore group is an extension to the Linux semaphore set. This provides a way to logically group semaphores. For example, it may be useful in a solution domain to group One-To-One semaphores differently from Many-to-One semaphores.
CoreLinux Semaphore Functional Requirements
General Requirements
---------------------
There will be no restriction on the type of the Semaphore that can be created other than system dependent resources.In this event, an exception will be thrown indicating, if possible, why the Semaphore could not be created.
The default mode for all Semaphore will be non-Balking.
All Semaphore Groups will support named creation.
All Semaphore Groups will support maximum group count creation. This identifies the number of maximum semaphores in the group.
All Semaphore Groups will support a segregation by type (One-to-One, One-to-Many, and Many-to-One).
All Semaphore Groups will support instrumentation.
All Semaphores will support having a user defined identifier.
All Semaphores will maintain a group and instance identifier.
Callers will be able to "get" a Semaphore by it's Group and Instance Identifier.
Callers will be able to "get" a Semaphore by it's Instance Identifier.
All Semaphores will support instrumentation.
All Semaphores will support access by only the process that creates it.
All Semaphores will support access by the process that creates it, and any children that the process spawns.
All Semaphores will support access by any process.
All Semaphores will support read only operations for each of the above access modes.
All Semaphores will support read/write operations for each of the above access modes.
All Semaphores will support a recursion disposition.
All other Semaphores will support a lock semantic in that the caller will wait until the lock is obtained.
All Semaphores will support the lock semantic with no-wait option so that the caller will return immediatley if the lock can not be immediatley obtained.
All Semaphores will support the lock semantic with timeout option so that the caller can indicate a maximum amount of time before giving up trying to obtain the lock.
General One-to-One Semaphore
----------------------------
One-to-One Semaphores will support a create and automatically lock capability.
One-to-One Semaphores will support a create and no-lock capability.
General One-to-Many Semaphore
-----------------------------
One-to-Many Semaphores will support a create with a maximum resource count.
One-to-Many Semaphores will support a create and automatically lock capability which means no resources are available.
One-to-Many Semaphores will support a create and no-lock capability which means all (maximum) resources are available.
One-to-Many Semaphores will support increasing the maximum count.
General Many-to-One Semaphore
-----------------------------
Many-to-One Semaphores will support a create with a maximum "listener" count
Many-to-One Semaphores will automatically lock upon creation. There is not option to create it unlocked.
Many-to-One Semaphores will support increasing the maximum "listener" count if balking mode enabled.
General Semaphore Groups
------------------------
CoreLinux++ will support a default, heterogeneous, Semaphore Group. Name TBD, maximum semaphore count TBD.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
This is the last draft before I turn it into a SRS.
CoreLinux++ Semaphore Requirement (1589) Draft - Version 0.4
A Semaphore is a protocol by which processes and/or threads agree to follow for the purpose of controlled access to a resource. The resource can be anything that the developer considers to need access controls on, such as memory, hardware, methods, computer instructions, and so on.
The protocol is pinned to the kernel which enforces blocking (being made to wait) the caller until a resource is available.
Callers can elect to avoid being put into a blocked state and return immediatley without control to the resource. Callers may also request that they are put into a blocked state for a specified amount of time. If, at the end of the specified time, the request has not been satisified, it is returned with a Timeout indicator.
The owner or creator of the semaphore can elect to enforce balking behavior on a Semaphore. When so designated, the Semaphore can turn back any request until some condition in their solution space is met regardless of the callers blocking options. If a caller access attempt is balked, is it returned with a Balked indicator.
Used to serialized access to a resource (one to one)
----------------------------------------------------
When used to prevent concurrent access to a resource, the caller must first obtain control of the associated Semaphore. When a caller has control of the Semaphore, the resource(s) that are associated with the Semaphore are considered locked and accessible by the caller. When the caller has completed access of the resource it relinquishes control and the resource is now considered unlocked.
Attempts may be made to access the resource by other threads of execution or from seperate processes. These callers are queued and the requestor is put into a blocked state. In this state the caller waits until the resource is unlocked. If multiple requests are blocking for the same control, the determination of which caller gains access next is, from a applications perspective, arbitrary.
When balking mode is enabled callers will be turned away as long as the Semaphore is locked.
Used to provide concurrent finite access (one to many)
------------------------------------------------------
When used in this fashion, a Semaphore can be used as an access count controller. The Semaphore is created, as determined by the solution domain, with the maximum number of concurrent active callers allowed. As long as the caller count does not reach the maximum, the arrival will be granted immediate access. When the maximum has been reached, arriving callers are blocked.
When balking mode is enabled callers will be turned away until the count reduces to less than maximum.
Used to block callers until an event occurs (many to one)
---------------------------------------------------------
When used in this fashion, a single Semaphore is used to let callers block until some event occurs. Unlike the serialzed access, where one caller at a time is released to gain access to a resource, when the designated event occurs all blocked callers are released at once.
The creator of this type of Semaphore can designate the maximum number of listeners that can wait on a single Semaphore event. When used in this manner, balking mode is automatically enabled.
When balking mode is enabled callers will be turned away until the number of listeners on the event drops below maximum.
Semaphore Groups
----------------
A Semaphore group is an extension to the Linux semaphore set. This provides a way to logically group semaphores. For example, it may be useful in a solution domain to group One-To-One semaphores differently from Many-to-One semaphores.
A Semaphore group acts as a semaphore factory, creating and destroying semaphores for the user.
CoreLinux Semaphore Functional Requirements
General Requirements
---------------------
There will be no restriction on the type of the Semaphore that can be created other than system dependent resources.In this event, an exception will be thrown indicating, if possible, why the Semaphore could not be created.
The default mode for all Semaphore will be non-Balking.
All Semaphore Groups will support named creation.
All Semaphore Groups will support maximum group count creation. This identifies the number of maximum semaphores in the group.
All Semaphore Groups will support a segregation by type (One-to-One, One-to-Many, and Many-to-One).
All Semaphore Groups will support instrumentation.
All Semaphore "creates" will pass through a Semaphore Group.
All Semaphore "destroys" will pass through a Semaphore Group.
All Semaphores will support having a user defined identifier.
All Semaphores will maintain a group and instance identifier.
Callers will be able to "get" a Semaphore by it's Group and Instance Identifier.
Callers will be able to "get" a Semaphore by it's Instance Identifier.
All Semaphores will support instrumentation.
All Semaphores will support access by only the process that creates it.
All Semaphores will support access by the process that creates it, and any children that the process spawns.
All Semaphores will support access by any process.
All Semaphores will support read only operations for each of the above access modes.
All Semaphores will support read/write operations for each of the above access modes.
All Semaphores will support a recursion disposition.
All other Semaphores will support a lock semantic in that the caller will wait until the lock is obtained.
All Semaphores will support the lock semantic with no-wait option so that the caller will return immediatley if the lock can not be immediatley obtained.
All Semaphores will support the lock semantic with timeout option so that the caller can indicate a maximum amount of time before giving up trying to obtain the lock.
General One-to-One Semaphore
----------------------------
One-to-One Semaphores will support a create and automatically lock capability.
One-to-One Semaphores will support a create and no-lock capability.
General One-to-Many Semaphore
-----------------------------
One-to-Many Semaphores will support a create with a maximum resource count.
One-to-Many Semaphores will support a create and automatically lock capability which means no resources are available.
One-to-Many Semaphores will support a create and no-lock capability which means all (maximum) resources are available.
One-to-Many Semaphores will support increasing the maximum count.
General Many-to-One Semaphore
-----------------------------
Many-to-One Semaphores will support a create with a maximum "listener" count
Many-to-One Semaphores will automatically lock upon creation. There is not option to create it unlocked.
Many-to-One Semaphores will support increasing the maximum "listener" count if balking mode enabled.
General Semaphore Groups
------------------------
CoreLinux++ will support a default, heterogeneous, Semaphore Group. Name TBD, maximum semaphore count TBD.
CoreLinux++ default group shall chain new group instances for user "get" operations.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
frankc,
In my programming, I have found a use for what I would call hierarchical semaphores. Perhaps your draft includes this capability, but I don't think it does. The idea is that a process may wait on a semaphore that is 'higher' than some other set of semaphores. As long as the 'lower' semaphores are held, the 'higher' one is unable to be granted. In fact, new 'lower' semaphores are allowed to be added to a 'higher' one's list, as long as at least one 'lower' one is still held. And of course, the newly added 'lower' ones can be granted as well.
using greater than to show what I mean:
given : s > s1 , s > s2 , s > s3
s1,s2,s3 are held by three threads or processes.
a 'parent' process is holding semaphore s.
a new process is granted semaphore s4
it can be added to the list for s, and all three
of s1,s2,s3 may be released, but s is still waiting on s4. when s4 is released, then s is granted.
To be complete, the opposite case of not allowing s1,s2,s3 etc to be granted if s is held is necessary, but I think your proposal already handles support for requiring 'lower' semaphores to wait when a 'higher' one is already granted,
and then to grant them when the 'higher' one is released.
Assuming of course, that releasing a semaphore can qualify as an event so I can use the capabilty to block callers until an event occurs (many to one).
David
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Oh, one other idea I had was that it would be nice
to attach a function to the semaphore. Kind of like a callback function. This would be useful for semaphores that have more than counter semantics necessary. I can imagine a semaphore that is tied to a bit map, and whether the semaphore is granted or not depends on whether particular bits are set or not. (with the decision of which bits to check dependent upon information about the caller) This bitmap kind of semantics may be too specialized to be added to the general Semaphore capability, but allowing the hook provides extension without cluttering the base code too much.
Finally, you mention in your document about a condition in the owner or creator's solution space being tied to turning back a request for a semaphore. Could you elaborate more on this ?
David
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
CoreLinux++ should provide Semaphore abstractions.
CoreLinux++ should provide a Mutual Exclusion semaphore abstraction.
CoreLinux++ should provide an Event semaphore. An event semaphore is a semaphore which can be blocked on until the target event occurs which releases all blocking threads.
frankc wrote:
> CoreLinux++ should provide an Event semaphore. An event semaphore is a semaphore
> which can be blocked on until the target event occurs which releases all blocking threads.
What about the non-broadcast signal (e.g., target event) that only releases the first blocked thread in the queue? (pthread_cond_signal vs. pthread_cond_broadcast)
What use case have you had in the past that makes this a possible requirement?
not an use case but a requirement, that being efficiency:
take for example a command queue that is being asynchronously updated by multiple threads and you have multiple threads pulling off of this queue and processing the commands/directives. say, at a certain point in time the queue is empty, this means all command processing threads are in a wait mode. say now that one command is pushed onto the queue. if the push generates a broadcast (ala, pthread_cond_broadcast semantics) this will wake up every waiting thread and they will all contend for the resource, in this case the queue mutex semaphore, and the winner will go onto process the command while the losers will go back to waiting. whereas if the push generated a signal (ala, pthread_cond_signal) only the next thread in line would be woken up and all the others would still be waiting.
in this situation, ultimately the results are the same: one thread acquires the queue semaphore lock and processes the command while the others end up waiting. but which scenario took more execution cycles to get to the same outcome?
this is the kind of example illustrated in _Programming with Posix Threads_ by Butenhoff (sp?).
also, if i remember correctly most multi-threading sources on the topic of event semaphore signalling say that if you can you should use the signal methodology instead of broadcast. i'll try to find a referential passage in a couple of my books to support this claim.
a good case for the command queue processing threads to use broadcast semantics is when not all the processing threads have the same thread priority--in this case you WANT the threads to contend for resources that way the higher priority thread(s) is/are honored.
on the other hand, when all the processing threads have the same thread priority it makes more sense to use signal semantics and use the time that would be spent on resource contention elsewhere.
hmm, it seems in my previous post i was talking about my opinionated take on what the experts recommend. here's what Butenhof (Programming with POXIS Threads, Addison Wesley 1997) has to say:
on page 81, paragraph 4:
<excerpt>
It is easy to think of "broadcast" as a generalization of "signal," but it is more accurate to think of signal as an optimization of broadcast. Remember that it is never wrong to use broadcast instead of signal since waiters have to account for intercepted and spurious wakes. The only difference, in fact, is efficiency: A broadcast will wake additional threads that will have to test their predicate and resume waiting. But, in general, you can't replace a broadcast with a signal. "When in doubt, broadcast."
Use signal when only one thread needs to wake up to process the changed state, and when <i>any</i> waiting thread can do so. ....
If you add a single item to a queue, and only threads waiting for an item to appear are blocked on the condition variable, then you should probably use a signal. That'll wake up a single thread to check the queue and let the others sleep undisturbed, avoiding unnecessary context switches. On the other hand, if you add more than one item to the queue, you will probably need to broadcast.
</excerpt>
This is from the man who wrote Digital UNIX's multi-threading facilities.
Does this meet the need for a valid use case describing the need for signal AND broadcast semantics/functionality?
So what I read are requirements for (and I am adding my own at this point):
1. A "broadcast" event - which doesn't care what priorities the waiting threads have (in some OS implementations, the thread with the highest priorit(y | ies) will be "signalled" first).
2. A priority based queue where only the front thread of the queue is signalled when the "event" triggers.
3. A priority based queue where each thread in the queue gets triggered sequentially.
4. Both 2 & 3 with no regard to priority.
In these cases, are the priorities based on thread priorities or some arbitrary type we provide?
The valid use case was for my understanding of your context. I appreciate it all.
comments:
#1 -- the underlying scheduler will take care of which thread actually wins the contention. for our purposes it is explicit enough to say broadcast will wake up all threads waiting on the event.
#2 -- again, the underlying scheduler will take care of which thread is actually signalled. it is explicit enough for our purposes to say a signal will wake up one and only one thread waiting on the event.
to answer your priorities question: when i speak of thread priority i'm thinking of the priority requested for the thread at creation time.
(this mechanism is roughly equivalent in almost all environments from java, to the unices even to win32)
i think specifying which waiters get woken up etc will only be important if we do decide to write our own userland scheduler. and if so these things and others should be captured as part of the scheduler's requirements.
#1 - Agreed
#2 - Agreed
Priority - fine.
Scheduler - agreed
Broadcast Events are event semaphores that notify all interested threads.
Selective events, when triggered, notify only one thread waiting on the target semaphore.
Hmm, I thought of something in my car on the way to work this morning concerning the latest proposition(s) for the event semaphore(s).
It amounts to this: I'm not so sure breaking the event semaphore into two distinct types would be as beneficial as instead incorporating the "broadcast" and "signal" semantics into 2 separate methods. A quick and valid use case scenario for this is:
We have multiple threads, as before, waiting on a queue to process commands pushed onto it. This queue is non-standard in that it has a batch push method (where you can push multiple commands onto the queue with one operation) as well as the expected standard push that places one command on the queue. Waking up threads in the latter instance is an easy consideration; we have one command so wake up merely one thread. In the former case, however, we need to consider the nature of desired command execution. If we have multiple threads to process commands (and for the sake of simplicity in this example) it makes sense that concurrent execution is expected. So in the case of a batch push we would want to broadcast to wake up all waiters and let them plow through the queue.
Another use case: we have a simple command queue (no batch push method) with multiple command processing threads that utilizes only a selective or signal event. What happens when it is time to shutdown? Sure we can call exit() or pthread_cancel() to stop the blocking threads from further execution--but we shouldn't make it a requirement. Instead, we should be able to set a thread-specific variable for each processing thread that tells them its time to shutdown (or set a global read only shutdown boolean) and then broadcast for them to wake up and move on, which in this case would be to clean up and terminate. But this option isn't available to use as we chose for efficiency to use the signal event. Out only recorse would be to cycle through a loop as many times as we have processing threads (assuming we KNOW how many we have) and wake up each one individually.
Granted all of my arguments above can be mitigated by tricky and complex coding (though waiting on multiple events is not a trivial coding task) but if the same end can be acheived with more simple code why not keep it simple?
To your first point, I am not making any implementation decisions here, just pointing out a requirement of behavior.
In your first use case I would submit that the choice of Broadcast versus Selective is the implementors choice that best fits their intent.
To the second use case, I have implemented in the past, and we are getting into specific problem space here (not a bad thing, just a thing), is a shutdown message is put on the queue. The broadcast wakes up the thread implementation and it detects the shutdown request and "poof", where the main thread (application) needs to block exiting until the threads are gone. No globals, no need for the queue to know the thread interface, no forcing of state into all derivations, etc.
alright then.
seems i got my panties in a premature bunch. i lost sight of the fact that your are specifying INTERFACE requirements. this allows for an event semaphore to implement both the selective and broadcast event interfaces.
> seems i got my panties in a premature bunch.
> i lost sight of the fact that your are
> specifying INTERFACE requirements. this
> allows for an event semaphore to implement
> both the selective and broadcast event
> interfaces.
As much as I would like to get to the
implementation, I think it would do diservice
to the process. The Signal requirements are
shaping up to where it is recognized that there
are two different specifications, each
providing seperate behavior. Following the
process we see that, from a analysis standpoint,
it would possibly be modeled as:
EventSemaphore---- isA ----> Semaphore
BroadcastSemaphore -- isA -->EventSemaphore
or the addition of
QueuedEventSemaphore-- isA -->EventSemaphore
And that is fine for analysis, you could even bring it to the design. Now in the design and thinking of implementation we consider scale, performance, derivations, etc. we may make a
decision that there is only EventSemaphore with
State determining what mode it operates in.
alright then.
seems i got my panties in a premature bunch. i lost sight of the fact that your are specifying INTERFACE requirements. this allows for an event semaphore to implement both the selective and broadcast event interfaces.
The CoreLinux++ thread abstractions can be handle or named referenced.
CoreLinux++ Semaphore Requirement (1589) Draft - Version 0.1
A Semaphore is a protocol by which processes and/or threads agree to follow for the purpose of controlled access to a resource. The resource can be anything that the developer considers to need access controls on, such as memory, hardware, methods, computer instructions, and so on.
The protocol is pinned to the kernel which enforces blocking (being made to wait) the caller until a resource is available.
Callers can elect to avoid being put into a blocked state and return immediatley without control to the resource. Callers may also request that they are put into a blocked state for a specified amount of time. If, at the end of the specified time, the request has not been satisified, it is returned with a Timeout indicator.
The owner or creator of the semaphore can elect to enforce balking behavior on a Semaphore. When so designated, the Semaphore can turn back any request until some condition in their solution space is met regardless of the callers blocking options. If a caller access attempt is balked, is it returned with a Balked indicator.
Used to serialized access to a resource (one to one)
----------------------------------------------------
When used to prevent concurrent access to a resource, the caller must first obtain control of the associated Semaphore. When a caller has control of the Semaphore, the resource(s) that are associated with the Semaphore are considered locked and accessible by the caller. When the caller has completed access of the resource it relinquishes control and the resource is now considered unlocked.
Attempts may be made to access the resource by other threads of execution or from seperate processes. These callers are queued and the requestor is put into a blocked state. In this state the caller waits until the resource is unlocked. If multiple requests are blocking for the same control, the determination of which caller gains access next is, from a applications perspective, arbitrary.
When balking mode is enabled callers will be turned away as long as the Semaphore is locked.
Used to provide concurrent finite access (one to many)
------------------------------------------------------
When used in this fashion, a Semaphore can be used as an access count controller. The Semaphore is created, as determined by the solution domain, with the maximum number of concurrent active callers allowed. As long as the caller count does not reach the maximum, the arrival will be granted immediate access. When the maximum has been reached, arriving callers are blocked.
When balking mode is enabled callers will be turned away until the count reduces to less than maximum.
Used to block callers until an event occurs (many to one)
---------------------------------------------------------
When used in this fashion, a single Semaphore is used to let callers block until some event occurs. Unlike the serialzed access, where one caller at a time is released to gain access to a resource, when the designated event occurs all blocked callers are released at once.
Balking mode is not available with this type Semaphore.
CoreLinux++ Semaphore Requirement (1589) Draft - Version 0.2
A Semaphore is a protocol by which processes and/or threads agree to follow for the purpose of controlled access to a resource. The resource can be anything that the developer considers to need access controls on, such as memory, hardware, methods, computer instructions, and so on.
The protocol is pinned to the kernel which enforces blocking (being made to wait) the caller until a resource is available.
Callers can elect to avoid being put into a blocked state and return immediatley without control to the resource. Callers may also request that they are put into a blocked state for a specified amount of time. If, at the end of the specified time, the request has not been satisified, it is returned with a Timeout indicator.
The owner or creator of the semaphore can elect to enforce balking behavior on a Semaphore. When so designated, the Semaphore can turn back any request until some condition in their solution space is met regardless of the callers blocking options. If a caller access attempt is balked, is it returned with a Balked indicator.
Used to serialized access to a resource (one to one)
----------------------------------------------------
When used to prevent concurrent access to a resource, the caller must first obtain control of the associated Semaphore. When a caller has control of the Semaphore, the resource(s) that are associated with the Semaphore are considered locked and accessible by the caller. When the caller has completed access of the resource it relinquishes control and the resource is now considered unlocked.
Attempts may be made to access the resource by other threads of execution or from seperate processes. These callers are queued and the requestor is put into a blocked state. In this state the caller waits until the resource is unlocked. If multiple requests are blocking for the same control, the determination of which caller gains access next is, from a applications perspective, arbitrary.
When balking mode is enabled callers will be turned away as long as the Semaphore is locked.
Used to provide concurrent finite access (one to many)
------------------------------------------------------
When used in this fashion, a Semaphore can be used as an access count controller. The Semaphore is created, as determined by the solution domain, with the maximum number of concurrent active callers allowed. As long as the caller count does not reach the maximum, the arrival will be granted immediate access. When the maximum has been reached, arriving callers are blocked.
When balking mode is enabled callers will be turned away until the count reduces to less than maximum.
Used to block callers until an event occurs (many to one)
---------------------------------------------------------
When used in this fashion, a single Semaphore is used to let callers block until some event occurs. Unlike the serialzed access, where one caller at a time is released to gain access to a resource, when the designated event occurs all blocked callers are released at once.
The creator of this type of Semaphore can designate the maximum number of listeners that can wait on a single Semaphore event. When used in this manner, balking mode is automatically enabled.
When balking mode is enabled callers will be turned away until the number of listeners on the event drops below maximum.
CoreLinux Semaphore Functional Requirements
General Reqquirements
---------------------
There will be no restriction on the type of the Semaphore that can be created other than system dependent resources.In this event, an exception will be thrown indicating, if possible, why the Semaphore could not be created.
The default mode for all Semaphore will be non-Balking.
All Semaphores will support access by only the process that creates it.
All Semaphores will support access by the process that creates it, and any children that the process spawns.
All Semaphores will support access by any process.
All Semaphores will support read only operations for each of the above access modes.
All Semaphores will support read/write operations for each of the above access modes.
All Semaphores will support a recursion disposition.
All other Semaphores will support a lock semantic in that the caller will wait until the lock is obtained.
All Semaphores will support the lock semantic with no-wait option so that the caller will return immediatley if the lock can not be immediatley obtained.
All Semaphores will support the lock semantic with timeout option so that the caller can indicate a maximum amount of time before giving up trying to obtain the lock.
General One-to-One Semaphore
----------------------------
One-to-One Semaphores will support a create and automatically lock capability.
One-to-One Semaphores will support a create and no-lock capability.
General One-to-Many Semaphore
-----------------------------
One-to-Many Semaphores will support a create with a maximum resource count.
One-to-Many Semaphores will support a create and automatically lock capability which means no resources are available.
One-to-Many Semaphores will support a create and no-lock capability which means all (maximum) resources are available.
One-to-Many Semaphores will support increasing the maximum count from the managing process only.
General Many-to-One Semaphore
-----------------------------
CoreLinux++ Semaphore Requirement (1589) Draft - Version 0.3
A Semaphore is a protocol by which processes and/or threads agree to follow for the purpose of controlled access to a resource. The resource can be anything that the developer considers to need access controls on, such as memory, hardware, methods, computer instructions, and so on.
The protocol is pinned to the kernel which enforces blocking (being made to wait) the caller until a resource is available.
Callers can elect to avoid being put into a blocked state and return immediatley without control to the resource. Callers may also request that they are put into a blocked state for a specified amount of time. If, at the end of the specified time, the request has not been satisified, it is returned with a Timeout indicator.
The owner or creator of the semaphore can elect to enforce balking behavior on a Semaphore. When so designated, the Semaphore can turn back any request until some condition in their solution space is met regardless of the callers blocking options. If a caller access attempt is balked, is it returned with a Balked indicator.
Used to serialized access to a resource (one to one)
----------------------------------------------------
When used to prevent concurrent access to a resource, the caller must first obtain control of the associated Semaphore. When a caller has control of the Semaphore, the resource(s) that are associated with the Semaphore are considered locked and accessible by the caller. When the caller has completed access of the resource it relinquishes control and the resource is now considered unlocked.
Attempts may be made to access the resource by other threads of execution or from seperate processes. These callers are queued and the requestor is put into a blocked state. In this state the caller waits until the resource is unlocked. If multiple requests are blocking for the same control, the determination of which caller gains access next is, from a applications perspective, arbitrary.
When balking mode is enabled callers will be turned away as long as the Semaphore is locked.
Used to provide concurrent finite access (one to many)
------------------------------------------------------
When used in this fashion, a Semaphore can be used as an access count controller. The Semaphore is created, as determined by the solution domain, with the maximum number of concurrent active callers allowed. As long as the caller count does not reach the maximum, the arrival will be granted immediate access. When the maximum has been reached, arriving callers are blocked.
When balking mode is enabled callers will be turned away until the count reduces to less than maximum.
Used to block callers until an event occurs (many to one)
---------------------------------------------------------
When used in this fashion, a single Semaphore is used to let callers block until some event occurs. Unlike the serialzed access, where one caller at a time is released to gain access to a resource, when the designated event occurs all blocked callers are released at once.
The creator of this type of Semaphore can designate the maximum number of listeners that can wait on a single Semaphore event. When used in this manner, balking mode is automatically enabled.
When balking mode is enabled callers will be turned away until the number of listeners on the event drops below maximum.
Semaphore Groups
----------------
A Semaphore group is an extension to the Linux semaphore set. This provides a way to logically group semaphores. For example, it may be useful in a solution domain to group One-To-One semaphores differently from Many-to-One semaphores.
CoreLinux Semaphore Functional Requirements
General Requirements
---------------------
There will be no restriction on the type of the Semaphore that can be created other than system dependent resources.In this event, an exception will be thrown indicating, if possible, why the Semaphore could not be created.
The default mode for all Semaphore will be non-Balking.
All Semaphore Groups will support named creation.
All Semaphore Groups will support maximum group count creation. This identifies the number of maximum semaphores in the group.
All Semaphore Groups will support a segregation by type (One-to-One, One-to-Many, and Many-to-One).
All Semaphore Groups will support instrumentation.
All Semaphores will support having a user defined identifier.
All Semaphores will maintain a group and instance identifier.
Callers will be able to "get" a Semaphore by it's Group and Instance Identifier.
Callers will be able to "get" a Semaphore by it's Instance Identifier.
All Semaphores will support instrumentation.
All Semaphores will support access by only the process that creates it.
All Semaphores will support access by the process that creates it, and any children that the process spawns.
All Semaphores will support access by any process.
All Semaphores will support read only operations for each of the above access modes.
All Semaphores will support read/write operations for each of the above access modes.
All Semaphores will support a recursion disposition.
All other Semaphores will support a lock semantic in that the caller will wait until the lock is obtained.
All Semaphores will support the lock semantic with no-wait option so that the caller will return immediatley if the lock can not be immediatley obtained.
All Semaphores will support the lock semantic with timeout option so that the caller can indicate a maximum amount of time before giving up trying to obtain the lock.
General One-to-One Semaphore
----------------------------
One-to-One Semaphores will support a create and automatically lock capability.
One-to-One Semaphores will support a create and no-lock capability.
General One-to-Many Semaphore
-----------------------------
One-to-Many Semaphores will support a create with a maximum resource count.
One-to-Many Semaphores will support a create and automatically lock capability which means no resources are available.
One-to-Many Semaphores will support a create and no-lock capability which means all (maximum) resources are available.
One-to-Many Semaphores will support increasing the maximum count.
General Many-to-One Semaphore
-----------------------------
Many-to-One Semaphores will support a create with a maximum "listener" count
Many-to-One Semaphores will automatically lock upon creation. There is not option to create it unlocked.
Many-to-One Semaphores will support increasing the maximum "listener" count if balking mode enabled.
General Semaphore Groups
------------------------
CoreLinux++ will support a default, heterogeneous, Semaphore Group. Name TBD, maximum semaphore count TBD.
This is the last draft before I turn it into a SRS.
CoreLinux++ Semaphore Requirement (1589) Draft - Version 0.4
A Semaphore is a protocol by which processes and/or threads agree to follow for the purpose of controlled access to a resource. The resource can be anything that the developer considers to need access controls on, such as memory, hardware, methods, computer instructions, and so on.
The protocol is pinned to the kernel which enforces blocking (being made to wait) the caller until a resource is available.
Callers can elect to avoid being put into a blocked state and return immediatley without control to the resource. Callers may also request that they are put into a blocked state for a specified amount of time. If, at the end of the specified time, the request has not been satisified, it is returned with a Timeout indicator.
The owner or creator of the semaphore can elect to enforce balking behavior on a Semaphore. When so designated, the Semaphore can turn back any request until some condition in their solution space is met regardless of the callers blocking options. If a caller access attempt is balked, is it returned with a Balked indicator.
Used to serialized access to a resource (one to one)
----------------------------------------------------
When used to prevent concurrent access to a resource, the caller must first obtain control of the associated Semaphore. When a caller has control of the Semaphore, the resource(s) that are associated with the Semaphore are considered locked and accessible by the caller. When the caller has completed access of the resource it relinquishes control and the resource is now considered unlocked.
Attempts may be made to access the resource by other threads of execution or from seperate processes. These callers are queued and the requestor is put into a blocked state. In this state the caller waits until the resource is unlocked. If multiple requests are blocking for the same control, the determination of which caller gains access next is, from a applications perspective, arbitrary.
When balking mode is enabled callers will be turned away as long as the Semaphore is locked.
Used to provide concurrent finite access (one to many)
------------------------------------------------------
When used in this fashion, a Semaphore can be used as an access count controller. The Semaphore is created, as determined by the solution domain, with the maximum number of concurrent active callers allowed. As long as the caller count does not reach the maximum, the arrival will be granted immediate access. When the maximum has been reached, arriving callers are blocked.
When balking mode is enabled callers will be turned away until the count reduces to less than maximum.
Used to block callers until an event occurs (many to one)
---------------------------------------------------------
When used in this fashion, a single Semaphore is used to let callers block until some event occurs. Unlike the serialzed access, where one caller at a time is released to gain access to a resource, when the designated event occurs all blocked callers are released at once.
The creator of this type of Semaphore can designate the maximum number of listeners that can wait on a single Semaphore event. When used in this manner, balking mode is automatically enabled.
When balking mode is enabled callers will be turned away until the number of listeners on the event drops below maximum.
Semaphore Groups
----------------
A Semaphore group is an extension to the Linux semaphore set. This provides a way to logically group semaphores. For example, it may be useful in a solution domain to group One-To-One semaphores differently from Many-to-One semaphores.
A Semaphore group acts as a semaphore factory, creating and destroying semaphores for the user.
CoreLinux Semaphore Functional Requirements
General Requirements
---------------------
There will be no restriction on the type of the Semaphore that can be created other than system dependent resources.In this event, an exception will be thrown indicating, if possible, why the Semaphore could not be created.
The default mode for all Semaphore will be non-Balking.
All Semaphore Groups will support named creation.
All Semaphore Groups will support maximum group count creation. This identifies the number of maximum semaphores in the group.
All Semaphore Groups will support a segregation by type (One-to-One, One-to-Many, and Many-to-One).
All Semaphore Groups will support instrumentation.
All Semaphore "creates" will pass through a Semaphore Group.
All Semaphore "destroys" will pass through a Semaphore Group.
All Semaphores will support having a user defined identifier.
All Semaphores will maintain a group and instance identifier.
Callers will be able to "get" a Semaphore by it's Group and Instance Identifier.
Callers will be able to "get" a Semaphore by it's Instance Identifier.
All Semaphores will support instrumentation.
All Semaphores will support access by only the process that creates it.
All Semaphores will support access by the process that creates it, and any children that the process spawns.
All Semaphores will support access by any process.
All Semaphores will support read only operations for each of the above access modes.
All Semaphores will support read/write operations for each of the above access modes.
All Semaphores will support a recursion disposition.
All other Semaphores will support a lock semantic in that the caller will wait until the lock is obtained.
All Semaphores will support the lock semantic with no-wait option so that the caller will return immediatley if the lock can not be immediatley obtained.
All Semaphores will support the lock semantic with timeout option so that the caller can indicate a maximum amount of time before giving up trying to obtain the lock.
General One-to-One Semaphore
----------------------------
One-to-One Semaphores will support a create and automatically lock capability.
One-to-One Semaphores will support a create and no-lock capability.
General One-to-Many Semaphore
-----------------------------
One-to-Many Semaphores will support a create with a maximum resource count.
One-to-Many Semaphores will support a create and automatically lock capability which means no resources are available.
One-to-Many Semaphores will support a create and no-lock capability which means all (maximum) resources are available.
One-to-Many Semaphores will support increasing the maximum count.
General Many-to-One Semaphore
-----------------------------
Many-to-One Semaphores will support a create with a maximum "listener" count
Many-to-One Semaphores will automatically lock upon creation. There is not option to create it unlocked.
Many-to-One Semaphores will support increasing the maximum "listener" count if balking mode enabled.
General Semaphore Groups
------------------------
CoreLinux++ will support a default, heterogeneous, Semaphore Group. Name TBD, maximum semaphore count TBD.
CoreLinux++ default group shall chain new group instances for user "get" operations.
frankc,
In my programming, I have found a use for what I would call hierarchical semaphores. Perhaps your draft includes this capability, but I don't think it does. The idea is that a process may wait on a semaphore that is 'higher' than some other set of semaphores. As long as the 'lower' semaphores are held, the 'higher' one is unable to be granted. In fact, new 'lower' semaphores are allowed to be added to a 'higher' one's list, as long as at least one 'lower' one is still held. And of course, the newly added 'lower' ones can be granted as well.
using greater than to show what I mean:
given : s > s1 , s > s2 , s > s3
s1,s2,s3 are held by three threads or processes.
a 'parent' process is holding semaphore s.
a new process is granted semaphore s4
it can be added to the list for s, and all three
of s1,s2,s3 may be released, but s is still waiting on s4. when s4 is released, then s is granted.
To be complete, the opposite case of not allowing s1,s2,s3 etc to be granted if s is held is necessary, but I think your proposal already handles support for requiring 'lower' semaphores to wait when a 'higher' one is already granted,
and then to grant them when the 'higher' one is released.
Assuming of course, that releasing a semaphore can qualify as an event so I can use the capabilty to block callers until an event occurs (many to one).
David
If I read this correctly, you would want the thread to block until numerous conditions are met, in this case semaphores, correct?
Oh, one other idea I had was that it would be nice
to attach a function to the semaphore. Kind of like a callback function. This would be useful for semaphores that have more than counter semantics necessary. I can imagine a semaphore that is tied to a bit map, and whether the semaphore is granted or not depends on whether particular bits are set or not. (with the decision of which bits to check dependent upon information about the caller) This bitmap kind of semantics may be too specialized to be added to the general Semaphore capability, but allowing the hook provides extension without cluttering the base code too much.
Finally, you mention in your document about a condition in the owner or creator's solution space being tied to turning back a request for a semaphore. Could you elaborate more on this ?
David