comp.lang.ada
 help / color / mirror / Atom feed
* How to simulate semaphores with Ada's tasks?
@ 2016-08-25  0:41 Andrew Shvets
  2016-08-25  1:04 ` Jeffrey R. Carter
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Andrew Shvets @ 2016-08-25  0:41 UTC (permalink / raw)


From what I've read, tasks do not have semaphores that can permit it to lock a piece of memory and prevent it from being accessed, is this correct?

If so, then the best possible way to simulate this is to have tasks send messages to one another and synchronize when something is locked/unlocked.  Is there a better approach?


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: How to simulate semaphores with Ada's tasks?
  2016-08-25  0:41 How to simulate semaphores with Ada's tasks? Andrew Shvets
@ 2016-08-25  1:04 ` Jeffrey R. Carter
  2016-08-25  1:44   ` Andrew Shvets
  2016-08-27 21:36   ` Andrew Shvets
  2016-08-25  7:39 ` Dmitry A. Kazakov
  2016-08-25  7:55 ` G.B.
  2 siblings, 2 replies; 9+ messages in thread
From: Jeffrey R. Carter @ 2016-08-25  1:04 UTC (permalink / raw)


On 08/24/2016 05:41 PM, Andrew Shvets wrote:
> 
> If so, then the best possible way to simulate this is to have tasks send
> messages to one another and synchronize when something is locked/unlocked.
> Is there a better approach?

Yes, you use protected objects.

-- 
Jeff Carter
"He had no conception of the instrument. He
was blowing into it."
Take the Money and Run
135


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: How to simulate semaphores with Ada's tasks?
  2016-08-25  1:04 ` Jeffrey R. Carter
@ 2016-08-25  1:44   ` Andrew Shvets
  2016-08-27 21:36   ` Andrew Shvets
  1 sibling, 0 replies; 9+ messages in thread
From: Andrew Shvets @ 2016-08-25  1:44 UTC (permalink / raw)


On Wednesday, August 24, 2016 at 9:04:50 PM UTC-4, Jeffrey R. Carter wrote:
> On 08/24/2016 05:41 PM, Andrew Shvets wrote:
> > 
> > If so, then the best possible way to simulate this is to have tasks send
> > messages to one another and synchronize when something is locked/unlocked.
> > Is there a better approach?
> 
> Yes, you use protected objects.
> 
> -- 
> Jeff Carter
> "He had no conception of the instrument. He
> was blowing into it."
> Take the Money and Run
> 135

Noted.  Reading up on it right now.

Thank you.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: How to simulate semaphores with Ada's tasks?
  2016-08-25  0:41 How to simulate semaphores with Ada's tasks? Andrew Shvets
  2016-08-25  1:04 ` Jeffrey R. Carter
@ 2016-08-25  7:39 ` Dmitry A. Kazakov
  2016-08-27 18:06   ` Andrew Shvets
  2016-08-25  7:55 ` G.B.
  2 siblings, 1 reply; 9+ messages in thread
From: Dmitry A. Kazakov @ 2016-08-25  7:39 UTC (permalink / raw)


On 25/08/2016 02:41, Andrew Shvets wrote:
> From what I've read, tasks do not have semaphores that can permit it
> to lock a piece of memory and prevent it from being accessed, is this
> correct?

It is unclear what you mean here. Semaphore blocks a resource, not 
necessarily memory. Technically you cannot block memory at the language 
level, e.g. using memory management registers. It is too low-level. So 
it is operations that are blocked with memory encapsulated somewhere 
into an object or a package.

> If so, then the best possible way to simulate this is to have tasks
> send messages to one another and synchronize when something is
> locked/unlocked.

That is called "monitor". It can be used to implement the semaphore too, 
but nobody does that. In most cases monitor is better than semaphore 
when that comes in question.

Semaphore has little if no use when k>1. Only mutex (semaphore k=1) is 
actively used.

> Is there a better approach?

Sometimes monitor is better sometimes mutex is.

Regarding mutex what kind of are you looking for? Plain? Reentrant? 
Read-write mutex? Arrays of mutexes?

In Ada synchronization objects like mutex are implemented using 
protected object. A plain mutex or semaphore is trivial to implement.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: How to simulate semaphores with Ada's tasks?
  2016-08-25  0:41 How to simulate semaphores with Ada's tasks? Andrew Shvets
  2016-08-25  1:04 ` Jeffrey R. Carter
  2016-08-25  7:39 ` Dmitry A. Kazakov
@ 2016-08-25  7:55 ` G.B.
  2 siblings, 0 replies; 9+ messages in thread
From: G.B. @ 2016-08-25  7:55 UTC (permalink / raw)


On 25.08.16 02:41, Andrew Shvets wrote:
> From what I've read, tasks do not have semaphores that can permit it to lock a piece of memory and prevent it from being accessed, is this correct?
>
> If so, then the best possible way to simulate this is to have tasks send messages to one another and synchronize when something is locked/unlocked.  Is there a better approach?
>

The thing is called Suspension_Object in Ada, see
Ada.Synchronous_Task_Control (RM D.10).

But, as others have said, it might be a good idea to
consider the use case and arrive at a protected resource.


-- 
"HOTDOGS ARE NOT BOOKMARKS"
Springfield Elementary teaching staff


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: How to simulate semaphores with Ada's tasks?
  2016-08-25  7:39 ` Dmitry A. Kazakov
@ 2016-08-27 18:06   ` Andrew Shvets
  0 siblings, 0 replies; 9+ messages in thread
From: Andrew Shvets @ 2016-08-27 18:06 UTC (permalink / raw)


On Thursday, August 25, 2016 at 3:39:50 AM UTC-4, Dmitry A. Kazakov wrote:
> On 25/08/2016 02:41, Andrew Shvets wrote:
> > From what I've read, tasks do not have semaphores that can permit it
> > to lock a piece of memory and prevent it from being accessed, is this
> > correct?
> 
> It is unclear what you mean here. Semaphore blocks a resource, not 
> necessarily memory. Technically you cannot block memory at the language 
> level, e.g. using memory management registers. It is too low-level. So 
> it is operations that are blocked with memory encapsulated somewhere 
> into an object or a package.
> 
> > If so, then the best possible way to simulate this is to have tasks
> > send messages to one another and synchronize when something is
> > locked/unlocked.
> 
> That is called "monitor". It can be used to implement the semaphore too, 
> but nobody does that. In most cases monitor is better than semaphore 
> when that comes in question.
> 
> Semaphore has little if no use when k>1. Only mutex (semaphore k=1) is 
> actively used.
> 
> > Is there a better approach?
> 
> Sometimes monitor is better sometimes mutex is.
> 
> Regarding mutex what kind of are you looking for? Plain? Reentrant? 
> Read-write mutex? Arrays of mutexes?
> 
> In Ada synchronization objects like mutex are implemented using 
> protected object. A plain mutex or semaphore is trivial to implement.
> 
> -- 
> Regards,
> Dmitry A. Kazakov
> http://www.dmitry-kazakov.de

Hello Dmitry,

Yes, resources is a better term.  What I'm looking for -- well, still learning about it, I'm quite new to this -- is really to learn more about mutexes.  I think I got my terminologies mixed up.  What I really meant is a mutex, not a semaphore (I want to be able to lock down a resource so that only one task has access to it at a time.)

A plain mutex is something that I'd like to start off with.  Thanks for your help, but for now I'd like to figure things out on my own, if I hit a wall I will post here.


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: How to simulate semaphores with Ada's tasks?
  2016-08-25  1:04 ` Jeffrey R. Carter
  2016-08-25  1:44   ` Andrew Shvets
@ 2016-08-27 21:36   ` Andrew Shvets
  2016-08-28  1:04     ` Jeffrey R. Carter
  1 sibling, 1 reply; 9+ messages in thread
From: Andrew Shvets @ 2016-08-27 21:36 UTC (permalink / raw)


On Wednesday, August 24, 2016 at 9:04:50 PM UTC-4, Jeffrey R. Carter wrote:
> 
> Yes, you use protected objects.
> 
> -- 
> Jeff Carter
> "He had no conception of the instrument. He
> was blowing into it."
> Take the Money and Run
> 135

Hello Jeff,

I do have a question now.  I've written an (at the bottom of this message) example on using a protected type.

My current understanding is that the protected type is a way to encapsulate a piece of data and then regulate which values can be assigned its insides (similar to how in Java there is a way to create a piece of code where only one thread at a time can run at any given moment.)  The example below has 5 tasks and each one tries to update the same unbounded string.  The goal was to create a small application with 5 tasks and each one fighting to update the same value.

Does my description make sense?  Or am I completely off-base?

https://gist.githubusercontent.com/anonymous/c8eee56143d534d837281953d86ac501/raw/cd2603babab42132cea68f71997960dd925fc4e8/gistfile1.txt


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: How to simulate semaphores with Ada's tasks?
  2016-08-27 21:36   ` Andrew Shvets
@ 2016-08-28  1:04     ` Jeffrey R. Carter
  2016-08-28  1:59       ` Andrew Shvets
  0 siblings, 1 reply; 9+ messages in thread
From: Jeffrey R. Carter @ 2016-08-28  1:04 UTC (permalink / raw)


On 08/27/2016 02:36 PM, Andrew Shvets wrote:
> 
> My current understanding is that the protected type is a way to encapsulate a
> piece of data and then regulate which values can be assigned its insides
> (similar to how in Java there is a way to create a piece of code where only
> one thread at a time can run at any given moment.)  The example below has 5
> tasks and each one tries to update the same unbounded string.  The goal was
> to create a small application with 5 tasks and each one fighting to update
> the same value.
> 
> Does my description make sense?  Or am I completely off-base?

In general, a protected object encapsulates a set of operations that are
mutually exclusive. Only one call to one operation may proceed at a time. (This
is not strictly correct, but it's close enough, it's simple, and an
implementation that works this way conforms to the standard.) It may also
encapsulate and hide some optional data that the operations operate on.

The PO in your example, as written, implements a standard monitor with a default
initial value for Unbounded_String (the default initial value is ""). A monitor
stores one value; calls to Put a new value overwrite the existing value; calls
to Get the value leave the value unaffected, and future calls to Get can return
the same value. This is sometimes described as having a destructive Put and
non-destructive Get. A queue, on the other hand, has a non-destructive Put and a
destructive Get. Your Empty component serves no purpose. If you had barriers
using Empty as in your comments, then your PO would be a bounded, blocking queue
with a maximum length of 1.

So from that point of view, you seem to understand how to use POs.

There's special syntax for singleton POs like yours:

protected Protected_01 is
   ...
end Protected_01;

This is equivalent to

protected type /anonymous/ is
   ...
end /anonymous/;

Protected_01 : /anonymous/;

If I were implementing the same functionality, I'd probably use String
externally and only use Unbounded_String when needed to store a String value:

protected Protected_String is
   procedure Put (Value : in String);
   function Value return String;
private -- Protected_String
   Current : Unbounded_String;
end Protected_String;

The body would convert as needed.

Looking at the rest of the example, your task is confused. The loop is executed
exactly once, so there's no reason for it. Your select has only a single
alternative, so there's no reason for it. Stripped of the output statements,
it's functionality is

begin
   accept Start ...;
   accept Quit;
   Protected_01.Insert ...;
end;

The default value of an uninitialized Unbounded_String is the null string, so given

V : Unbounded_String;

V's value is "" and there's no reason to explicitly initialize it to that.
However, if you do need to refer to the null string value, you can use
Null_Unbounded_String, which is probably clearer and better than
To_Unbounded_String ("").

There's no guarantee that multiple tasks writing to the same
Ada.Text_IO.File_Type will give you useful results.

-- 
Jeff Carter
"Monsieur Arthur King, who has the brain of a duck, you know."
Monty Python & the Holy Grail
09


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: How to simulate semaphores with Ada's tasks?
  2016-08-28  1:04     ` Jeffrey R. Carter
@ 2016-08-28  1:59       ` Andrew Shvets
  0 siblings, 0 replies; 9+ messages in thread
From: Andrew Shvets @ 2016-08-28  1:59 UTC (permalink / raw)


On Saturday, August 27, 2016 at 9:04:26 PM UTC-4, Jeffrey R. Carter wrote:
> On 08/27/2016 02:36 PM, Andrew Shvets wrote:
> > 
> > My current understanding is that the protected type is a way to encapsulate a
> > piece of data and then regulate which values can be assigned its insides
> > (similar to how in Java there is a way to create a piece of code where only
> > one thread at a time can run at any given moment.)  The example below has 5
> > tasks and each one tries to update the same unbounded string.  The goal was
> > to create a small application with 5 tasks and each one fighting to update
> > the same value.
> > 
> > Does my description make sense?  Or am I completely off-base?
> 
> In general, a protected object encapsulates a set of operations that are
> mutually exclusive. Only one call to one operation may proceed at a time. (This
> is not strictly correct, but it's close enough, it's simple, and an
> implementation that works this way conforms to the standard.) It may also
> encapsulate and hide some optional data that the operations operate on.
> 
> The PO in your example, as written, implements a standard monitor with a default
> initial value for Unbounded_String (the default initial value is ""). A monitor
> stores one value; calls to Put a new value overwrite the existing value; calls
> to Get the value leave the value unaffected, and future calls to Get can return
> the same value. This is sometimes described as having a destructive Put and
> non-destructive Get. A queue, on the other hand, has a non-destructive Put and a
> destructive Get. Your Empty component serves no purpose. If you had barriers
> using Empty as in your comments, then your PO would be a bounded, blocking queue
> with a maximum length of 1.
> 
> So from that point of view, you seem to understand how to use POs.
> 
> There's special syntax for singleton POs like yours:
> 
> protected Protected_01 is
>    ...
> end Protected_01;
> 
> This is equivalent to
> 
> protected type /anonymous/ is
>    ...
> end /anonymous/;
> 
> Protected_01 : /anonymous/;
> 
> If I were implementing the same functionality, I'd probably use String
> externally and only use Unbounded_String when needed to store a String value:
> 
> protected Protected_String is
>    procedure Put (Value : in String);
>    function Value return String;
> private -- Protected_String
>    Current : Unbounded_String;
> end Protected_String;
> 
> The body would convert as needed.
> 
> Looking at the rest of the example, your task is confused. The loop is executed
> exactly once, so there's no reason for it. Your select has only a single
> alternative, so there's no reason for it. Stripped of the output statements,
> it's functionality is
> 
> begin
>    accept Start ...;
>    accept Quit;
>    Protected_01.Insert ...;
> end;
> 
> The default value of an uninitialized Unbounded_String is the null string, so given
> 
> V : Unbounded_String;
> 
> V's value is "" and there's no reason to explicitly initialize it to that.
> However, if you do need to refer to the null string value, you can use
> Null_Unbounded_String, which is probably clearer and better than
> To_Unbounded_String ("").
> 
> There's no guarantee that multiple tasks writing to the same
> Ada.Text_IO.File_Type will give you useful results.
> 
> -- 
> Jeff Carter
> "Monsieur Arthur King, who has the brain of a duck, you know."
> Monty Python & the Holy Grail
> 09

You are correct, the loop runs only once.  It should be like so:

else
  Ada.Text_IO.Put_Line("Task is inserting!");
  Protected_01.Insert(Task_Custom_String);
  delay 0.0;
end select;

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2016-08-28  1:59 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-25  0:41 How to simulate semaphores with Ada's tasks? Andrew Shvets
2016-08-25  1:04 ` Jeffrey R. Carter
2016-08-25  1:44   ` Andrew Shvets
2016-08-27 21:36   ` Andrew Shvets
2016-08-28  1:04     ` Jeffrey R. Carter
2016-08-28  1:59       ` Andrew Shvets
2016-08-25  7:39 ` Dmitry A. Kazakov
2016-08-27 18:06   ` Andrew Shvets
2016-08-25  7:55 ` G.B.

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox