In my cases, services are often physical ("real world") resources. E.g., client1 would like to use water (at a certain rate of flow) to irrigate some portion of the landscape. Service grants this request. Some time later -- before client1 has finished using the resource -- client2 would like to use water to "take a shower".
The service knows (because of codified rules) that taking a shower is a higher priority (in terms of "importance") than watering the yard (because the system has defined it to be so!). In an ideal world, service could notify client1 and *command* that it release the resource, "now". Await acknowledgement that it has released the resource, then grant it to client2. Presumably, client1 will immediately issue a request for the resource -- which the service will defer -- because client2 is now using it and has a higher priority (think preemption) than client1!
"Service" can perform neither client1 nor client2's actions with that resource -- doing so would require intimate knowledge of their respective applications.
The flaw in this "cooperative" approach is client1 need not comply with that "command". Or, might be sluggish in complying. Then, client2 sees an artificial delay in when it can legitimately use the resource. Similarly, it might be reluctant to relinquish it when the fire suppression system client *needs* it. (i.e., these are all just different "priorities"/importances to the service.)
How long do you allow the current user to hold onto the resource after notification that it MUST be relinquished? What if your message got lost on the network -- does your protocol include time for a reissued "command" to be delivered SO client1 CAN COOPERATIVELY RELINQUISH THE RESOURCE? What happens *in* client1 when it "discovers" the resource has been withdrawn?
(I.e., I contend client1 has to be able to handle the asynchronous revocation of the resource *without* notification, regardless.)
So, you have to implement a fail-safe mechanism whereby you can forcibly revoke the service from a noncompliant client -- and deal with the consequences of that.
[For other examples, consider a client that wants to operate the air conditioner compressor while another has already been granted use of a certain amount of AC power for the electrically fired kiln. While air conditioning seems like it should be a high priority/importance task, turning off the kiln before the glaze is completely baked will probably alter the appearance of the piece -- possibly rendering the work "useless" (along with all of the electricity expended to bring it to that point).Or, imagine the resource is the MIPS available on some processor that is underutilized in the system. Or, some portion (KB/MB) of a fixed size, persistent store ("Yeah, I know you'd love to store your children's birthdates. And, I know we told you, previously, that you could use this space for that. But, we
*really* need to store this critical log message until someone has a chance to review it!")]See above. Server is just metering out resources so the only "action" it can provide is granting or denying access to that resource.
But that's how I see these things. In much the same way that a scheduler invocation INTERRUPTS a currently executing task's access to the "CPU".
The difference is the interrupted task has a contract with the scheduler that it will *try* to resume the task WHERE IT LEFT OFF at some later point in time. AS IF, the interrupt had never happened (unless the task is actually watching the wall clock or anything else that changes with the passage of REAL time!). I.e., the task is not asked for it's *consent* to be interrupted -- even if it might never be resumed!
Similarly, a task can be killed asynchronously. There is no prerequisite to notify it, in advance (pre-notification can make its shutdown more orderly -- but, also requires more elapsed time *and* coding!)
Or, whose messages/replies aren't being delivered due to network congestion, delays, etc. (uniprocessor and SMP techniques don't map directly into the distributed world where these guarantees are a lot harder to meet *in* a timeliness context!)
[Remember, a message has to get from its originator, through that scheduler (i.e., when is the originator allowed to execute?), through the network stack (is it an RT stack??), onto the media up through the receiving stack (again, RT?) and dispatched to a task running at some unknown LOCAL priority before that task can even *see* it.]By contrast, notification (e.g., signal) that the resource has ALREADY been revoked has an implicit "fait accompli" -- regardless of how long the message took to transit.
Neither is a particularly great way of dealing with the problem. But, cooperation just seems to rife for abuse. Even well-intentioned clients might be busy when the request (command) arrives. And, may have complex requirements to wind down their use of that resource in a timely fashion E.g., they might be acting as an agent/server for some related "resource" that some *other* client is currently using. And, that client will need to be "notified" that it must release that resource... before the original client can release the resource it has been commanded to release.
(How long do you sit patiently -- defering the needs of that original client2 -- while you try to be polite/accommodating of client1 et al.?)
I'm willing to live with signals *if* I can come up with a clean framework that makes it easy for developers to implement them, correctly. (so a client isn't chugging along in ignorance thinking that it still owns that resource that has ALREADY been revoked and repurposed).
[E.g., you *think* you are watering the yard but, in fact, there is no water flowing through *your* pipes! Or, you *think* a CPU is busy working on some aspect of your "job" but it has been reallocated to some other purpose... you'll be waiting *forever* for it to complete!]Yet another example of how bending requires more thought/work than simply throwing excess capacity at a problem! :-/
--don