[Company Logo Image]    

Home Feedback Contents Search

4.3 Example
4.1 Structure 4.2 Compiling 4.3 Example 4.4 Socket 4.5 OOP 4.6 Competing 4.7 Optimization 4.8 Connector 4.9 Merging 4.10 Emulation 4.11 Ordered Calls 4.12 Last-Only 4.13 Group Inputs 4.14 Complex Sys. 4.15 Prior Art... 4.16 Redundant SW 4.17 Visual SW 

Back Home Up Next

4.3 Basic Programming Example   

const int n=100; 

some_type A[n],B[n],C[n];

int total_count;

//----------------------------------------------------

detach void done_item()

{  ++total_count;

   if ( total_count==n )

      all_done();

   return;

};

//----------------------------------------------------

detach void add_item(int i)

{  return;

   C[i] = A[i]+B[i]; //Time consuming operation     

   done_item();

};

//----------------------------------------------------

detach void add_arrays()

total_count=0;

   for ( int i=0; i<n; i++ )

      add_item(i);

};

FIG. 2: An example of adding elements of two arrays concurrently

FIG. 2 shows an example of adding elements of two arrays concurrently in C/C++ language extended by stress-flow as the simplest example how stress-flow achieves concurrency. The example is purposely trivial, but it actually is a template for performing very useful and complex matrix operations in parallel using stress-flow. For example, to convert this template into a very useful code for multiplying two matrices, A, B, and C would be defined as matrices and the C[i]=A[i]+B[i] instruction with loop calculating a single element of the result matrix. Keyword “detach” differentiates a stress-flow atom from a regular procedure. The choice of naming is dictated by the fact that there are several ways to use the stress-flow atom stressed/relaxed structure concept, with other keyword(s) needed, which will be explained later. The initiating routine “add_arrays” calls stress-flow atom “add_item” in a loop. Since “add_atom” has nothing in the stressed section, it immediately releases its lock and starts to do its time consuming job while the calling routine continues with its loop. Up to “n” add_item atoms are soon running in parallel if only there are enough processors (real or virtual) waiting for work. If there were only k processors available at the moment, “add_arrays” will stall while trying to initiate execution of k+1 call to “add_item.” Since previously scheduled “add_item” number k is still waiting for a processor, it was unable to mark and release add_item’s lock. As soon as add_item k gets the processor, it releases add_item’s lock which resumes operation of add_arrays.

In order for the example to be of any use, there must be a way to know when the whole job is finished. This is accomplished by means of add_item calling “done_item” stress-flow atom. Unlike add_item, the done_item has all of its work inside the stressed section. This is necessary, because its job is to properly count all finished add_items and this requires not allowing more than one process to run that code at a given moment. Since “done_item” has no relaxed section at all, a good implementation of compilation of the example would only insert proper done_item lock “reserve” and “release” instructions, without trying to make calls to done_item run as separate processes – no defined relaxed section denotes nothing that needs to be run in parallel. In fact, a properly optimized compilation of “done_item” on multi-processor architecture would simply issue proper “interlocked” increment-and-compare shared memory access commands.

const int n=100

some_type A[n],B[n],C[n];

//----------------------------------------------------

detach

{  int total_count;

   void done_item()

   {  ++total_count;

      if ( total_count==n )

         all_done();

      return;

   };

   void zero_count()

   {  total_count=0;

   }; 

};

//----------------------------------------------------

detach void add_item(int i)

{  return;

   C[i] = A[i]+B[i]; //Time consuming operation     

   done_item();

};

//----------------------------------------------------

detach void add_arrays()

zero_count();

   for ( int i=0; i<n; i++ )

      add_item(i);

};

FIG. 3: A better written example of adding elements of two arrays concurrently

In order to stress this function of exclusion better, the needed variables (only to be accessed in stressed operations associated with specific lock) should be defined together as part of the same “detach” structure. Modified, more proper original example is shown in FIG. 3. Variable “total_count” is declared together with all the operations on it: “done_item” and “zero_count”.  This structural method is not only making code clearer to the reader. It also allows the compiler to either completely disallow access to “total_count” outside stressed sections of “done_item” and “zero_count”; or encapsulate it with the reserve/release instructions for the lock shared by all three items listed within discussed detach block. Existing in any object-oriented language mechanisms (“public” or “private” designators) can be used to indicate which outcome is desired.

The example described above is good to begin demonstrating stress-flow as it uses extreme cases of stress-flow atom layouts – one having nothing in the stressed section, the other having nothing in the relaxed section. The full strength of stress-flow is however the fact that both stressed and relaxed sections can initiate calls to other stress-flow atoms. The placement is clear means to declare what needs to be done while tying up others and what cannot, what may happen in parallel on the some data and what is forbidden. In particular, all exclusion of others from shared resources is done through placing code in the stressed section, all actual concurrency is accomplished by placing code in the relaxed section.

Back Home Up Next
Send mail to info@stressflow.com with questions or comments.
Copyright © 2005-2010. All Rights Reserved. Patents Pending in Multiple Jurisdictions.
First published 03/29/06. Last modified: 06/25/10