` Printed Icetips Article

Icetips Article



Windows API: Using Critical sections in C55
2002-11-04 -- Jim Kane
 
Newsgroups: comp.lang.clarion


the way I do it
myclass class()
method1 procedure()
method2 procedure()
  end
AsyncMyClass class(myclass)
AsyncMethod1 procedure()
AsyncMethod2 procedure()
  end
AsyncMyclass.AsyncMethod1 procedure()
  entercs()
  SELF.method1()
  leavecs()
AsyncMyClass.AsyncMethod2 procedure()
  entercs()
  SELF.method2
  leavecs()
myclass.method1 procedure()
  code
  SELF.Method2

myclass.method2 procedure()
  code
  !do something

That way I can choose to add the slower threadsafe wrapper or not.  There
are only two times you'll need this that I can think of.  The class is
declared globally -or- you pass the address of a class from one thread to
another and access the class from more than one thread (common way to
implement toolboxes).
Also many classes have very little member data and inside the class you can
write private accessor methods that ensure the data is accessed serially
but not protect the class methods themself.  The protection is only invoked
when accessing the private data and for a lot of method calls that dont need
the member data, you don't need to worry about it.

Jim Kane



"Ronald van Raaphorst"  wrote in message
news:3dc61920@news.softvelocity.com...
> Hi Jim,
>
> Thanks for the explanation. One more question:
>
> I assume the class uses only one critical section ID or handle or
whatever,
> which it uses in all it's methods?
> So if I call method2 from method1, and both use the EnterCriticalSection
> statement as the first statement in the method, that's no problem? (i.e.
> They're can be nested?)
>
> MyClass.Method1 PROCEDURE
>   CODE
>      EnterCriticalSection(SELF.MyCS)
>      ....
>      SELF.Method2
>      ...
>      LeaveCriticalSection
>
> MyClass.Method2 PROCEDURE
>   CODE
>      EnterCriticalSection(SELF.MyCS)
>      ....
>      DoSomething
>      ...
>      LeaveCriticalSection
>
> Then I can be sure that method1 is executed (and therefore method2 too)?
>
> The CRITICAL_SECTION equate is a long, isn't it?
>
> Thanks
> Ronald
>
>
>
> "jim kane"  schreef in bericht
> news:3dc31e35$1@news.softvelocity.com...
> > you dont need to do that now but will in 5.6
> > the general scenario is
> > in the init method of your global class create the critical section and
> new
> > you queue.
> > add methods to get a queue record and return the fields.  Same for set.
> > For all methods that access the queue, put entercriticalsection() at the
> > start of the method and leavecriticalsection()
> > at the end of the method.  Method should have one exit point.  Before
the
> > leavecriticalsection you should have copied data from the global queue
> > buffer to the method parameters (or local data) for a get and from the
> > parameters into the queue and done the add(q)/put(q) on a set.
> > I think if you try it once you'll have no problems.
> >
> > the biggest problem with critical sections is no time out.
> > entercriticalsection blocks for ever until it gets in.  So it's
important
> > not to have any message() or other potentially lenghthy operations
between
> > entercriticalsection and leavecriticalsections or every thread wanting
to
> > read the queue waits until the message() box is closed.
> > Jim kane
> >
> > "Ronald van Raaphorst"  wrote in message
> > news:3dc242d2@news.softvelocity.com...
> > > Hi all,
> > >
> > > I have this global object (class) which manages a queue (C55F)
> > > Every (threaded) procedure may ask the class to read or write some
data,
> > > using class methods only. That is, the data of the global object is
> > > protected from the world outside.
> > > The data in the object is not threaded, as the filebuffers are for
> > example.
> > >
> > > As each (threaded) procedure can call the global object methods at any
> > time,
> > > I have the need to create critical sections in the global object's
> > methods,
> > > or at least to be sure that during the execution of a method, no other
> > > threads can interfere by calling the same method.
> > >
> > > A method could do something like this:
> > >
> > > MyGlobalClass.DoSomethingWithID PROCEDURE(ULONG ID)
> > >    CODE
> > >        ! Start of a critical section
> > >        SELF.FetchQueue(ID)
> > >        ! From here on, I must rely on the fact that the same
queuerecord
> > is
> > > in the buffer
> > >        DoStuff...
> > >        PUT(SELF.MyQueue)
> > >        ! End of critical section
> > >
> > > Now I'm not sure, but does clarion use some kind of cooperative
> > > multitasking? That is, thread one can only execute if thread two is
'in
> > the
> > > accept statement', waiting for thread one to return to it's accept
> > > statement. IOW, is it true that a thread can only execute if all other
> > > threads are 'waiting' in their accept statement? (I do not say accept
> > loop,
> > > because most accept loops have a case statement to differentiate
between
> > > different events for different fields, and that I see as executing
> code).
> > >
> > > If the above is true, then I do not have to implement critical
sections,
> > > because the nature of the accept statement makes sure that a thread
runs
> > > untill it encounters the accept statement again. (I do not use YIELD
and
> I
> > > do not have nested accept statements)
> > >
> > > If the above is not true, then I do have to create pieces of 'run
> without
> > > interruptions' snippets. Are there any examples of this kind of code
> > around?
> > >
> > > Thanks in advance,
> > >
> > > Ronald
> > > Compad
> > >
> > >
> >
> >
>
>



Printed May 4, 2024, 11:16 am
This article has been viewed/printed 35118 times.
Google search has resulted in 54 hits on this article since January 25, 2004.