From 36d1c639a88bc52e787e24f2903778a25bd27f7f Mon Sep 17 00:00:00 2001 From: eiffel-org Date: Wed, 5 Aug 2015 13:25:04 +0000 Subject: [PATCH] Updated SCOOP documentation. (Author: Roman Schmocker) git-svn-id: https://svn.eiffel.com/eiffel-org/trunk@1428 abb3cda0-5349-4a8f-a601-0c33ac3a8c38 --- .../solutions/_images/scoop-regions.png | Bin 0 -> 25223 bytes .../solutions/_images/scoop-regions.png.data | 3 + .../concurrent-eiffel-scoop/index.wiki | 262 +----------------- .../scoop-asynchronous-calls.wiki | 136 +++++++++ .../scoop-design-by-contract.wiki | 57 ++++ .../scoop-examples/index.wiki | 5 +- .../scoop-exceptions.wiki | 107 +++++++ .../scoop-exclusive-access.wiki | 145 ++++++++++ .../scoop-getting-started.wiki | 74 +++++ .../scoop-implementation.wiki | 42 ++- .../scoop-practical-matters.wiki | 52 ---- .../scoop-regions-processors.wiki | 114 ++++++++ .../scoop-separate-calls.wiki | 126 +++++++++ 13 files changed, 807 insertions(+), 316 deletions(-) create mode 100644 documentation/current/solutions/_images/scoop-regions.png create mode 100644 documentation/current/solutions/_images/scoop-regions.png.data create mode 100644 documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-asynchronous-calls.wiki create mode 100644 documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-design-by-contract.wiki create mode 100644 documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-exceptions.wiki create mode 100644 documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-exclusive-access.wiki create mode 100644 documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-getting-started.wiki delete mode 100644 documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-practical-matters.wiki create mode 100644 documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-regions-processors.wiki create mode 100644 documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-separate-calls.wiki diff --git a/documentation/current/solutions/_images/scoop-regions.png b/documentation/current/solutions/_images/scoop-regions.png new file mode 100644 index 0000000000000000000000000000000000000000..25d233a0ad9899656738474963aebe19cd4a1322 GIT binary patch literal 25223 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 Ly7Kn&ouK~$JY9FY literal 0 HcmV?d00001 diff --git a/documentation/current/solutions/_images/scoop-regions.png.data b/documentation/current/solutions/_images/scoop-regions.png.data new file mode 100644 index 00000000..c4add29f --- /dev/null +++ b/documentation/current/solutions/_images/scoop-regions.png.data @@ -0,0 +1,3 @@ +title=SCOOP Regions +text=The memory of a SCOOP program, splitted into regions. +path=content/scoop-regions diff --git a/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/index.wiki b/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/index.wiki index e392db1f..be3109ee 100644 --- a/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/index.wiki +++ b/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/index.wiki @@ -3,275 +3,29 @@ [[Property:uuid|151838da-80f0-5381-d557-5c5b7727647d]] ==Overview== -SCOOP is ''Simple Concurrent Object-Oriented Programming''. SCOOP allows developers to create object-oriented software systems which will take advantage of multiple, concurrently active execution vehicles. Additionally, SCOOP programming is done at a level of abstraction above the specific details of these implementation vehicles. Read further to get a better idea of what all this means, but for now, the primary message should be: SCOOP is concurrent software development made easy. The basic SCOOP ideas were first published as early as 1993. Since that time, considerable research and development has refined the SCOOP into the model that is implemented in EiffelStudio today. +SCOOP is ''Simple Concurrent Object-Oriented Programming''. SCOOP allows developers to create object-oriented software systems which will take advantage of multiple, concurrently active execution engines while providing strong guarantees that allow programmers to reason like in sequential programs. Read further to get a better idea of what all this means, but for now, the primary message should be: SCOOP is concurrent software development made easy. The basic SCOOP ideas were first published as early as 1993. Since that time, considerable research and development has refined the SCOOP into the model that is implemented in EiffelStudio today. -{{Note|As you begin to use SCOOP, be sure to read the sections of the documentation on [[SCOOP practical matters]] and consider compiling and working with some of the many [[SCOOP examples]].}} +{{Note|As you begin to use SCOOP you should make sure that you correctly set up your project. Information on how to do this can be found at [[Getting Started with SCOOP]]. Also consider compiling and working with some of the many [[SCOOP examples]].}} ==Concurrency== -Concurrency in computation is a situation in which we can expect that a running computer system will have multiple computations executing simultaneously in a controlled fashion to achieve the goals of the system. The simultaneous executions can be handled by widely diverse computational vehicles: separate networked computer systems, separate processors in the same CPU, separate processor cores on a single chip, separate processor threads within a process, separate processes on the same CPU, etc. +Concurrency in computation is a situation in which we can expect that a running computer system will have multiple computations executing simultaneously in a controlled fashion to achieve the goals of the system. The simultaneous executions can be handled by widely diverse computational engines: separate networked computer systems, separate processors in the same CPU, separate processor cores on a single chip, separate processor threads within a process, separate processes on the same CPU, etc... Concurrent systems would not cause much trouble if the portions of the systems on different processors, processes, or threads were completely independent, that is, they shared no resources. But that would be a rare case indeed. In a concurrent system, simultaneously executing software elements can and do share resources and communicate with each other. This is where the problems can arise; problems in the form of various synchronization issues such as [http://en.wikipedia.org/wiki/Race_condition#Computing race conditions], [http://en.wikipedia.org/wiki/Atomicity_(programming) atomicity] violations, and [http://en.wikipedia.org/wiki/Deadlock deadlocks]. The issues boil down to two essential problems in allowing access to shared resources: -:# '''Avoid deadlocks''': make certain that no two executing threads of control wait perpetually because each needs a resource which is under the control of the other. -:# '''Ensure fairness''': make certain that every participating thread of control eventually gets the opportunity to execute. +:# '''Provide Safety''': Make certain that nothing bad ever happens, like two threads that access the same memory in no defined order, or an invalid interleaving of operations that causes the program to crash. +:# '''Ensure Progress''': Make certain that every participating thread eventually gets the opportunity to execute. Possible problems in this category are deadlocks, starvation (a thread keeps a lock forever, causing another one to wait), fairness etc... Concurrency control is a rich research area in computer science. Consequently, many schemes have been designed to control concurrent computation. -Indeed, SCOOP is such a model for concurrent computation. SCOOP differs from many other research efforts. +SCOOP is such a model for concurrent computation which differs in some areas from other research efforts. -First, it is a goal of SCOOP to abstract the notion of concurrency to a level above the tools and techniques that are currently available in the target concurrency environment. What this means is that if you were writing a system with multiple process threads, you could do that without SCOOP, using the tools that are currently used in multi-threaded programming, like semaphores and mutexes. Or you could write it in SCOOP using only the SCOOP mechanisms. Likewise with SCOOP, a system intended to run on multiple processors or multiple processor cores also could be written using only those same SCOOP mechanisms that you used for the multi-threaded system. +First, it is a goal of SCOOP to abstract the notion of concurrency to a level above the tools and techniques that are currently available. What this means is that if you were writing a system with multiple process threads, you could do that without SCOOP, using the tools that are currently used in multi-threaded programming, like semaphores and mutexes. Or you could write it in SCOOP using only the SCOOP mechanisms. Likewise with SCOOP, a system intended to run on multiple processors or multiple processor cores also could be written using only those same SCOOP mechanisms that you used for the multi-threaded system. -Second, the SCOOP model, as it is implemented in Eiffel, depends primarily upon Design by Contract with slightly changed contract semantics, and a single new keyword separate added to the Eiffel programming language. As you will see, the semantics of preconditions differ with concurrent execution versus sequential. Also, there are other underlying concepts and rules that need to be understood, but the point is that concurrent Eiffel using SCOOP will look a lot like sequential Eiffel. +Second, the SCOOP model depends primarily upon Design by Contract with slightly changed contract semantics, and a single new keyword separate added to the Eiffel programming language. As you will see, the semantics of preconditions differ with concurrent execution versus sequential. Also, there are other underlying concepts and rules that need to be understood, but the point is that concurrent Eiffel using SCOOP will look a lot like sequential Eiffel. Third, SCOOP uses the common act of argument passing to identify the necessity for guaranteeing exclusive access. We will examine the details of how all this fits together and what it means to you as you begin to build concurrent software in Eiffel using SCOOP. - -==Object-oriented computation== - -Eiffel’s familiar model for object-oriented computation: - - - - x.f (a) - - - -continues to be valid in SCOOP. But the way we understand the model differs slightly. In sequential Eiffel we would refer to this as a ''feature call'', with a client calling feature f on a supplier object (the call’s target) currently attached to the entity x, and possibly passing arguments represented by a. We might alternatively refer to x.f (a) as a ''feature application''; specifically the application of feature f to the object associated with x. This is fine in sequential Eiffel, but as you will see, in SCOOP we have to make a distinction between ''feature call'' and ''feature application''. The distinction will become clear as we discuss the notions of processors and separate calls. - -==Processors== - -In the context of SCOOP, ''processor'' is an abstract notion. - - -{{definition|Processor|An autonomous thread of control capable of the sequential execution of instructions on one or more objects.}} - - -{{info|About processors: -
1) Processor is an abstract notion. As such it does not imply any specific concurrency implementation. -
2) At any given time, every runtime object is handled by exactly one processor. A single processor can handle any number of objects.}} - - -In traditional, sequential Eiffel, although we realize that there is some processor which executes our systems, we don’t usually give it much thought. When we do, we generally regard it as a hardware entity on which our software can run. - -The term ''processor'' (or, interchangeably, ''handler'') is vital to SCOOP and thought of in a slightly different way than in traditional Eiffel, i. e., not just as a hardware processor. In a concurrent system, there may be any number of ''processors''. Here the term is used in a more abstract sense than before. In SCOOP we think of a processor as any autonomous thread of control capable of applying features to objects. At the level of the SCOOP model, processors are not restricted to a particular type of hardware or software. So, if you were writing software for a hardware implementation with multiple processors, those real processors might correspond to the ''processors'' of SCOOP. But if you were writing a system using multiple process threads, then those threads might correspond to SCOOP ''processors''. - - -{{note|In the initial SCOOP implementation in EiffelStudio version 6.8, multiple process threads are the only supported concurrency mechanism. So, each SCOOP processor is implemented as a separate thread of execution in a single process. }} - - -Multiple processors in SCOOP come into play when feature calls on a particular object may actually be applied by a different processor than the one on which the feature call was issued. Of course, this is the important distinction between feature call and feature application that was mentioned above. In SCOOP, the processor which does the feature application may be different from the one that does the feature call. So you can think of feature call as being the ''logging'' or ''queuing'' of a request to have a feature applied. - -==Separate types and separate calls== - -SCOOP introduces the notion of ''separateness''. - - -{{definition|Separate type|A type which has been declared including the keyword separate.}} - - -{{definition|Separate call|A feature call whose target is of a separate type.}} - - -The determining factor for the use of multiple processors is the use of ''separate types'' and ''separate calls''. In a running system, every object is handled by a processor, but in the case in which there are no separate types or separate calls in a system, then only one processor will be used during execution, i. e., all calls will be non-separate ... and, consequently, there is no SCOOP-based concurrent processing present. - -If an entity uses the keyword separate in its declaration, such as: - - - - my_x: separate X - - - -it indicates that the application of features to an object attached to my_x may occur on a different processor than the one on which the feature call was made. Such calls, my_x.f, would be considered separate calls. Additionally, the type of my_x is the separate type separate X. - -A feature call on my_x, say: - - - - my_x.f - - - -would generally be considered a separate call, simply because it is a feature call on an object of a separate type, and therefore could be applied on a different processor. You will see now that separate calls are valid only in certain contexts. - -==Access to shared resources== - -As mentioned above, the main issue with concurrent systems is the proper control of access to resources that can be shared among simultaneously executing processors. - -Traditional solutions to the problem involve the use of “critical sections” of code. These are sections of code in which the shared resource is accessed. Only one processor is allowed to be executing the critical section at a time. So if one process wants to execute the critical section and another is already doing so, then the first must wait. Process synchronization schemes ensure this “mutual exclusion” of access to the critical section. - -Rather than using critical sections, SCOOP relies on the mechanism of argument passing to assure controlled access. As a result, there is a restriction placed on separate calls. - - -{{Rule|name=Separate argument|text=A separate call a_x.f (a) is valid only if a_x is an argument of the enclosing routine.}} - - -So, according to this rule, for a separate call to be valid, the target of the call must be a formal argument of the routine in which the call occurs. The code below contains both an invalid separate call and a valid one. - - - - my_separate_attribute: separate SOME_TYPE - - ... - calling_routine - -- One routine - do - my_separate_attribute.some_feature -- Invalid call: Feature call on separate attribute - enclosing_routine (my_separate_attribute) -- Separate attribute passed as argument - end - - enclosing_routine (a_arg: separate SOME_TYPE) - -- Another routine - do - a_arg.some_feature -- Valid call: Feature call on separate argument - end - - - -In the code above, my_separate_attribute is a class attribute declared as a separate type. In the first line in calling_routine a direct feature call is made to apply some_feature to my_separate_attribute. This is an invalid separate call. The second line calls feature enclosing_routine and passes my_separate_attribute as an argument. enclosing_routine takes an argument of type separate SOME_TYPE. Within enclosing_routine it is valid to call some_feature on a_arg. - - -{{SeeAlso|The launch_producer feature of the [[Producer-consumer|producer-consumer]] example, a feature which exists for the purpose of compliance with the separate argument rule.}} - - -In calling_routine above, the call to enclosing_routine has a separate argument: - - - enclosing_routine (my_separate_attribute) -- Separate attribute passed as argument - - -Because the argument my_separate_argument is of a separate type, then it is subject to be handled by a processor different from the one on which the call to enclosing_routine occurs. As a result, the execution of enclosing_routine will be delayed until the time that the processor which handles my_separate_argument is available for exclusive access. This type of delay is described by the ''Wait rule''. - - -{{Rule|name=Wait|text=A routine call with separate arguments will execute when all corresponding processors are available and hold them exclusively for the duration of the routine.}} - - -{{SeeAlso|
-1) The {PHILOSOPHER}.eat feature of the [[Dining philosophers|dining philosophers]] example. This feature has two separate arguments, and will wait to execute until the processors associated with both are available.
-2) [[SCOOP Implementation#The Wait Rule|How the ''Wait rule'' is implemented]] in EiffelStudio. }} - - -===Controlled expressions=== - -Valid targets for separate calls, like a_arg in enclosing_routine above are said to be ''controlled''. - - -{{definition|Controlled/uncontrolled expression|An expression is '''controlled''' if it is attached and either:
1) It is of a non-separate type
2) It is of a separate type and it is handled by the same processor as one of the separate arguments to the enclosing routine.

Otherwise it is '''uncontrolled'''.}} - - -What the definition of ''controlled expression'' means is that such an expression is controlled with respect to the processor handling the context in which the expression is used (the current context) ... and that means that all objects necessary to the expression are under control of (available for exclusive access by) the current processor and cannot be modified by other processors. - - -==Synchronous and asynchronous feature calls== - -As stated above, when we think of the execution of sequential Eiffel, we tend to equate feature call and feature application. That is, it is expected that for a sequence of two feature calls: - - - - x.f - y.g - - - -that the feature application of x.f will complete before y.g begins. - -In concurrent Eiffel with SCOOP things are different. This is because a particular feature call, x.f, may occur on one processor, and the consequent feature application (of feature f to x) may occur on a different processor. - - -{{definition|Synchronous feature call|A feature call in which the execution of the calling client does not proceed until the feature application has completed. }} - - -{{definition|Asynchronous feature call|A feature call which causes the “logging” of a request by a client for the associated feature application to be executed by the supplier’s processor. }} - - -After an asynchronous feature call, the execution of the client proceeds immediately, possibly in parallel with the application of the feature on some other processor. We'll revisit this point after a look at what it takes for a call to be synchronous or asynchronous. - - -===What makes a call synchronous or asynchronous?=== - -First, every feature call is either a synchronous feature call or an asynchronous feature call. For a particular call, the following rules determine which it is: - -A feature call is '''synchronous''' in the following cases: - -:S1 It is a non-separate call. -:S2 It is a separate call: -::S2.1 To a query, or -::S2.2 To a command which has at least one actual argument which is of a reference type and either -:::S2.2.1 A separate argument of the enclosing routine, or -:::S2.2.2 Current. - -A feature call is '''asynchronous''' in the following case: -:A1 It is a separate call to a command with no arguments, or arguments not meeting the criteria of S2.2 above. - -Let’s look a little closer at those cases determining synchronous calls. - -Case S1 is the case of typical sequential Eiffel, where all calls are non-separate, and therefore synchronous. Of course, even in concurrent Eiffel with SCOOP, plenty of non-separate calls will occur, and these will be synchronous. - -Case S2.1 says that if a separate call is a query it must be synchronous. This is because even though the feature application will probably occur on a different processor, the instructions following the query will likely depend up on the result of the query, so they must wait until the feature application completes. This situation is known as ''wait by necessity''. - -Case S2.2 describes a situation in which a call provides at least one actual argument that is Current or is a separate formal argument of the call’s enclosing routine. In this case the client is calling a procedure and passing arguments which are ''controlled'' in the context of the calling routine. That is, the actual arguments are objects upon which the client processor has exclusive access in the enclosing routine. In order for the supplier processor to be able to apply the feature (presumably accessing the argument objects in the process), the client must pass its exclusive access to these objects on to the supplier. This is done through a mechanism called ''access passing''. Because the client has passed its exclusive access to the supplier processor, it cannot continue execution until the called feature has been applied by the supplier processor, and the supplier processor has restored the exclusive access back to the client. Therefore, this type of call must be synchronous. - -Now consider the only case, Case A1, determining asynchronous calls. - -Separate calls to commands are asynchronous (except as in case S2.2). This means that when a client executes an asynchronous feature call, it “logs” the need for its associated feature application. But then rather than waiting for the feature application to complete, the client routine continues execution of instructions beyond the asynchronous call. - -It is in this case that concurrent computation is achieved. The processor of the client object is free to continue processing while the processor handling the target of the asynchronous feature call applies that feature. - - -==Design by Contract and SCOOP== - -The backbone of the Eiffel Method is design by contract. Preconditions, postconditions, and class invariants are used in Eiffel for extending software interfaces into software specification. This is essentially the same in concurrent Eiffel with SCOOP as it is in traditional, sequential Eiffel. However, because of the concurrent nature of processing under SCOOP, the runtime semantics of the elements of Design by Contract are different for concurrent systems. - - -===Preconditions=== - -The role of the precondition is somewhat different in SCOOP than in sequential Eiffel. In non-concurrent Eiffel we view the precondition of a routine as defining a set of obligations on potential callers of the routine. That is, the set of conditions that must be true before correct execution of the routine can be expected. So, we could look at the precondition clauses in sequential Eiffel as '''correctness conditions'''. A typical example might be a square root routine that returns the square root of a passed argument value. A precondition clause, i. e., a correctness condition, for this routine will be that the argument must be non-negative. It is the responsibility of the caller to ensure that this property of the argument holds at the time of the feature call. - -In concurrent Eiffel, the same correctness conditions are still valid, but there are cases in which we must view the clients role here a little differently. In the case of a precondition clause that depends upon an [[Concurrent Eiffel with SCOOP#Controlled expressions|uncontrolled]] object, even if the client tests the condition ahead of the call, there is no assurance that action by some other concurrent processor may have invalidated the precondition clause between the time that the check was made and the time that the feature application takes place. So, the client cannot be held responsible establishing that this clause holds. This type of precondition clause is called an '''uncontrolled precondition clause'''. - -{{definition|Controlled/uncontrolled assertion''' (precondition or postcondition) '''clause| A precondition or postcondition clause for a feature f is controlled if, after substitution of actual arguments for formal arguments, the clause involves only calls on entities which are controlled in the context of the routine which is the caller of f.

Otherwise it is an '''uncontrolled assertion''' (precondition or postcondition) '''clause'''. }} - - -So, the determination of whether a particular precondition or postcondition clause is controlled or uncontrolled depends upon the context of the calling routine. That means that a particular clause on feature f might be considered controlled when f is called by one caller, but uncontrolled when called by a different caller. - -Uncontrolled precondition clauses demand an adaptation of precondition semantics: - -{{Info|A violation of a '''controlled precondition clause''' will cause an exception in the caller as soon as the violation is detected. A violation of an '''uncontrolled precondition clause''' does not result in an exception in the caller. Rather, the feature application waits to execute until such time as the precondition clause holds. }} - - -So, the client's responsibility is limited to those precondition clauses that are controlled. Uncontrolled precondition clauses become '''wait conditions'''. - - -{{SeeAlso|The {PRODUCER}.store feature in the [[Producer-consumer|producer-consumer]] example. When called by {PRODUCER}.produce it becomes a '''wait condition'''.}} - - -===Postconditions=== - -As with preconditions the effect of concurrent execution can make a difference in how postconditions are viewed. - -If a routine has executed correctly, then the postcondition of the routine will hold at the time that it terminates ... this is true whether or not concurrency is involved. However, when a postcondition involves separate calls or entities, clients must be cautious about how they depend upon the state guaranteed by postconditions. - - -===Class invariants=== - -The '''separate argument rule''' above tells us that separate calls are valid only on targets which are formal arguments of their enclosing routines. Because class invariants are not routines and therefore have no arguments, separate calls are not allowed in class invariants. - - -{{Info|Technically, it should be possible in a class invariant to code an inline agent that gets passed arguments of separate types, then execute separate calls within the inline agent. But generally, it can be assumed that class invariants contain no separate calls. }} - - -The semantics of class invariants will be the same as in sequential Eiffel, precisely because invariants must include only non-spearate calls. To put it the terms of SCOOP, the class invariant ensuring the validity of any particular object will be evaluated entirely by the processor handling that object. - - - - - - - - - - diff --git a/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-asynchronous-calls.wiki b/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-asynchronous-calls.wiki new file mode 100644 index 00000000..b746f6ee --- /dev/null +++ b/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-asynchronous-calls.wiki @@ -0,0 +1,136 @@ +[[Property:title|Asynchronous Calls]] +[[Property:weight|6]] +[[Property:uuid|d3d3873c-5c84-7566-547e-1ede38544081]] +==Overview== + +As we've seen in [[Separate Calls]], feature calls to a non-separate target are always synchronous. +Furthermore, queries are always synchronous as well, because the caller has to wait for the result. + +{| border="1" +|- +! Target +! Query +! Command +|- +| non-separate +| synchronous +| synchronous +|- +| separate +| synchronous +| potentially asynchronous +|} + +Asynchronous calls can therefore only happen on commands with a separate target. +Indeed, such calls are by default executed asynchronously, but there are some important exceptions to this rule. +A command to a separate target is executed synchronously if any of the following applies: +* The client (caller) and supplier (target) region are the same. +* The target region is passive. +* The callee needs a lock currently held by the caller (lock passing). +* The caller holds the locks of the callee (separate callbacks). + +== Triggers for Synchronization == + +=== Same Regions === + +The first case happens when a reference is declared separate, but happens to be non-separate. This case follows directly from the type system: A non-separate type A always conforms to its variation separate A. At run-time such cases can be detected with an object test: + + +sep_object: separate A +--... +if attached {A} sep_object as non_sep_object then + -- ... +end + + +=== Passive Regions === + +In the SCOOP model, a passive region does not have a processor attached to it. +This means that clients of the passive region need to apply features logged against a passive region themselves. +The logical consequence of this is that all call to a passive region, including commands, are executed synchronously. + +=== Lock Passing === + +Lock passing is another source of synchronization. It is one of the trickiest issues to detect, and to fully understand it we must first introduce a few more definitions. + +In [[Exclusive Access]] we have learned that an object is ''controlled'' if it appears as a formal argument of the enclosing routine. SCOOP however always grants exclusive access over a whole region. We therefore introduce the new term ''Lock'': + +{{definition|Lock|Exclusive access to a SCOOP region and all objects therein.}} + +Note the difference between ''controlled'' and ''locked'': +* ''Controlled'' applies to a single object, whereas ''locked'' applies to a region. +* The ''controlled'' property can be determined statically at compile-time, whereas ''locked'' is determined at runtime. +* The set of ''controlled'' objects of a processor is always a subset of the set of objects in ''locked'' regions. + +{{note|In terms of implementation, a ''lock'' corresponds to an open call queue to a region.}} + +Now consider a small classes HASH_STORAGE and EXAMPLE: + +class HASH_STORAGE feature + + hash_code: INTEGER + + set_hash_code (a_string: separate STRING) + do + hash_code := a_string.hash_code + end +end + +class EXAMPLE feature + + run (a_hash_storage: separate HASH_STORAGE; a_string: separate STRING) + do + a_hash_storage.set_hash_code (a_string) + io.put_integer (a_hash_storage.hash_code) + end +end + + +You might notice a problem here: +In the feature {EXAMPLE}.run, exclusive access to 'a_hash_storage' and 'a_string' is guaranteed by the SCOOP semantics. +Or in other words, the corresponding regions are ''locked''. The feature {HASH_STORAGE}.set_hash_code however needs access to ''a_string'' as well. +In the SCOOP model, as seen so far, this would result in a deadlock. The handler of the HASH_STORAGE object waits for exclusive access on the string object, and the EXAMPLE object waits for the query {HASH_STORAGE}.hash_code to return. + +To resolve this problem, SCOOP implements a technique called ''Lock Passing''. +Locks on regions can be passed to the handler of the target of a separate call. +Lock passing happens whenever the client processor (the handler of the EXAMPLE object) has locked a region that holds an object which is passed as an actual argument to a separate call. Note that this also includes non-separate reference objects, because a processor always holds a lock over its own region. + +When a client has passed its locks to the supplier processor, it cannot continue execution until the called feature has been applied by the supplier processor, and the supplier processor has given back the locks to the client. Therefore, this type of call must be synchronous. + +{{note|During lock passing, a processor gives away all the locks that it currently holds, including the lock on itself.}} + +{{note| Lock passing happens for every synchronous call, in particular also for queries and passive processors.}} + +The advantage of lock passing is that it enables some very common programming patterns without triggering a deadlock. The disadvantage, however, is that it's hard to tell '''when''' it happens. However, there are a few cases when lock passing is guaranteed to happen, namely when the actual argument passed to a separate call is +* a formal argument of the enclosing routine, +* of a non-separate reference type or +* Current. + +There are, however, some cases where it's not immediately obvious that lock passing happens. +For example, a region might be locked because of a controlled argument somewhere further up in the call stack (i.e. not the enclosing routine, but the caller of that routine), or because an object is passed as an argument which happens to be on the same region as one of the controlled objects. + +There is a workaround to disable lock passing for a specific call: + +async_call (a_procedure: separate PROCEDURE [ANY, TUPLE]) + do + a_procedure.call (Void) + end + +example (a_object: separate ANY) + do + async_call (agent a_object.some_feature (Current)) + end + + +The feature async_call can be defined somewhere in the project and can be reused. The downside is that an agent needs to be created, but there's no lock passing happening, because all arguments to the agent are closed and only Void is passed to the separate call which cannot trigger lock passing. +However, this mechanism should be used with some care, because it's easy to run into one of the above mentioned deadlocks. + +=== Separate Callbacks === + +The last occurrence of synchronous calls is closely related to lock passing. If a processor '''A''' has passed a non-separate reference argument to another processor '''B''', and thus has passed its locks away, it cannot proceed its execution. Sometimes however processor '''B''' has to log some calls back to '''A''', which is called a ''separate callback''. + +{{definition|Separate Callback | A separate call where the caller holds the locks of the callee. }} + +During a separate callback processor '''B''' has to give back the locks it has previously received from '''A'''. +This in turn means '''B''' has to wait until '''A''' has finished its execution of the separate callback and returned the locks, which effectively makes the call synchronous. + diff --git a/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-design-by-contract.wiki b/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-design-by-contract.wiki new file mode 100644 index 00000000..62b16d6f --- /dev/null +++ b/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-design-by-contract.wiki @@ -0,0 +1,57 @@ +[[Property:title|Design by Contract in SCOOP]] +[[Property:link_title|Design by Contract]] +[[Property:weight|5]] +[[Property:uuid|f8df5904-d1ee-31d7-f618-fb8bf1ddc876]] + +The backbone of the Eiffel Method is design by contract. Preconditions, postconditions, and class invariants are used in Eiffel for extending software interfaces into software specification. This is essentially the same in concurrent Eiffel with SCOOP as it is in traditional, sequential Eiffel. However, because of the concurrent nature of processing under SCOOP, the runtime semantics of the elements of Design by Contract are different for concurrent systems. + + +==Preconditions== + +The role of the precondition is somewhat different in SCOOP than in sequential Eiffel. In non-concurrent Eiffel we view the precondition of a routine as defining a set of obligations on potential callers of the routine. That is, the set of conditions that must be true before correct execution of the routine can be expected. So, we could look at the precondition clauses in sequential Eiffel as '''correctness conditions'''. A typical example might be a square root routine that returns the square root of a passed argument value. A precondition clause, i. e., a correctness condition, for this routine will be that the argument must be non-negative. It is the responsibility of the caller to ensure that this property of the argument holds at the time of the feature call. + +In concurrent Eiffel, the same correctness conditions are still valid, but there are cases in which we must view the clients role here a little differently. +In the case of a precondition clause that depends on a separate object, even if the client tests the condition ahead of the call, there is no assurance that action by some other concurrent processor may have invalidated the precondition clause between the time that the check was made and the time that the feature application takes place. + +In SCOOP preconditions can therefore additionally take the role of a '''wait condition'''. +Wait conditions are useful for cases where the caller can't guarantee that a property on an object is true at the time of the call, but it knows that it will eventually become true. +If a wait condition fails, the current processor will stall its execution, release the locks on its arguments, and wait until the precondition is fulfilled. + +A typical example is a CONSUMER object trying to dequeue an item from a shared BUFFER. +In the following example, the precondition in {CONSUMER}.consume is treated as a wait condition: + +class CONSUMER feature + consume (a_buffer: separate BUFFER): INTEGER + require + not_empty: not a_buffer.is_empty + do + Result := a_buffer.item + a_buffer.remove + end +end + + +A precondition clause is only treated as a wait condition when there's a separate call. +However, the opposite is not true - not all precondition clauses with a separate call are treated as wait conditions. +The rule is a bit tricky to understand, but as a general rule of thumb, a precondition violation is raised when the SCOOP runtime detects that there's no possibility that a precondition clause may become true in the future if the routine releases its exclusive access. + +{{Info| Alright, here are the exact rules: The decision depends on the context of the '''caller''' of the routine. +If one of the separate objects used as a target in a precondition clause is ''locked'' (see definition in [[Asynchronous Calls]]) in the context of the caller, the precondition is treated as a correctness condition. Otherwise, it is a wait condition.}} + +{{SeeAlso|The {PRODUCER}.store feature in the [[Producer-consumer|producer-consumer]] example. When called by {PRODUCER}.produce it becomes a '''wait condition'''.}} + +==Postconditions== + +As with preconditions the effect of concurrent execution can make a difference in how postconditions are viewed. + +If a routine has executed correctly, then the postcondition of the routine will hold at the time that it terminates. This is true whether or not concurrency is involved. However, when a postcondition involves separate calls, clients must be cautious about how they depend upon the state guaranteed by postconditions. + + +==Class invariants== + +The '''separate argument''' rule in [[Separate Calls]] tells us that a separate call is valid only on a target which is a formal arguments of the enclosing routine. Because class invariants are not routines and therefore have no arguments, separate calls are not allowed in class invariants. + +{{Info|Technically, it should be possible in a class invariant to code an inline agent that gets passed arguments of separate types, then execute separate calls within the inline agent. But generally, it can be assumed that class invariants contain no separate calls. }} + +The semantics of class invariants will be the same as in sequential Eiffel, precisely because invariants must include only non-spearate calls. To put it the terms of SCOOP, the class invariant ensuring the validity of any particular object will be evaluated entirely by the processor handling that object. + diff --git a/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-examples/index.wiki b/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-examples/index.wiki index 1fa9c2f9..4337e405 100644 --- a/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-examples/index.wiki +++ b/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-examples/index.wiki @@ -1,8 +1,5 @@ [[Property:title|SCOOP examples]] -[[Property:weight|0]] +[[Property:weight|8]] [[Property:uuid|75ddd9e0-3baf-655a-748f-ea8765a1d06d]] The examples for SCOOP that are distributed with EiffelStudio are solutions to classic and not-so-classic concurrency problems. - - - diff --git a/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-exceptions.wiki b/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-exceptions.wiki new file mode 100644 index 00000000..a5b75c37 --- /dev/null +++ b/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-exceptions.wiki @@ -0,0 +1,107 @@ +[[Property:title|Exceptions in SCOOP]] +[[Property:link_title|Exceptions]] +[[Property:weight|7]] +[[Property:uuid|4f760d0c-ff3b-5f8a-7d43-9be855cef17a]] +== Introduction == + +Exceptions are a rather nasty issue in concurrency. +In a shared memory system, an exception can leave a system in an inconsistent state, for example because they jump over an unlock operation. +In message passing systems on the other hand they can introduce unnecessary synchronization just to make sure that no exception happened, or they can create havoc because the recipient of an exception message is no longer in a state where it can handle it. + +For SCOOP, the exception mechanism was carefully designed with the following goals in mind: +* Comprehensibility: It should be easy to understand +* Compatibility with exceptions in sequential programs +* Consistency: An exception should not leave objects in a tainted state. +* Asynchrony: Exceptions should not restrict the level of concurrency. + +== Exception Propagation == + +Within a single processor, exceptions propagate just like in a sequential program. +When a routine encounters an exception, the rescue clause is entered, and if no retry statement is present, the exception is propagated to the caller. +This ensures backwards compatibility with sequential programs, because when there's only the root processor, the semantics are exactly the same. +Furthermore, this mechanism has proven itself useful for restoring invariants after an exception in order to bring objects to a consistent state. + +The interesting case is when an exception propagates between regions, which happens during a separate call. +In that case there are two possibilities: +* The call is synchronous: The exception is propagated to the client region. +* The call is asynchronous: The exception is not propagated, because the client is busy executing something else. Instead, the supplier region is marked as ''dirty''. + +This decision was mostly made to ensure comprehensibility. +Propagating an exception to the client in an asynchonous call would be really hard to handle. +The client would have to be ready to handle an exception at any point in time, and there would have been a need for an additional language mechanism to protect critical sections. +Because of these reasons SCOOP restricts exception propagation to synchronous calls only. + +== Dirty Regions == + +A region marked as dirty has suffered an exception in an asynchronous call, which could not be propagated to its client. +The dirty mark has a big impact for future separate calls. + +{{rule|name=Semantics of Dirty Regions|text=
+1) All calls logged to a dirty region, whether synchronous or asynchronous, are ignored.
+2) A synchronous separate feature call to a dirty region immediately triggers an exception in the client. Afterwards, the region is clean again.}} + +The reason for these rules is that a series of commands and a subsequent query often depend on each other. +For example, a first call may instruct the target region to open a file, the next call to append a string to it, followed by a query to get the new size of the file. +If the first call already fails, there's no point in executing subsequent calls. +Even worse, it can make recovery from exceptions very hard to do in the client if it has no idea which calls have been successfully executed after the first exception. + +The dirty mark will also vanish when an region is unlocked. +{{rule|name=Unlocking Dirty Regions|text=After releasing a lock on a dirty region, the region is clean again.}} + +This is probably the most controversial design decision, because '''it allows for exceptions to be lost'''. +During the design of the exception mechanism, there was a choice of two other solutions. +One would have been to add an automatic "safeguard" synchronization whenever an unlock operation happens, during which exceptions could be propagated. The obvious downside is that it severely limits the uses of asynchrony. +Another solution would have been to preserve the exception, and raise it in the client that next logs a call. +The last solution only partially solves the problem (there might be no next client logging a query at all), but introduces a new problem that processors can get an exception completely out of context. +However, the main reason to choose the "forget-upon-unlock" solution over the other two is that it's easy to simulate the behaviour manually (as you'll see in the next section), while it's impossible to have a "forget-upon-unlock" semantics if one of the other models is used. + +{{info|Upon lock passing, the dirtyness of a region is preserved.}} + +== Preventing Exception Loss == + +One way to prevent exceptions from being lost is to add a synchronous query at the end of a routine: + + +put_character (c: CHARACTER; a_file: separate MY_FILE) + local + l_sync: POINTER + do + a_file.open + a_file.put_character (c) + a_file.close + -- This ensures that exceptions are propagated: + l_sync := a_file.default_pointer + end + + +Another possibility is to store the failure in the separate object: + + +class MY_FILE feature + + is_tainted: BOOLEAN + + open + do + -- Open a file. + rescue + is_tainted := True + end + + -- other features +end + +class CLIENT feature + + put_character (c: CHARACTER; a_file: separate MY_FILE) + do + if a_file.is_tainted then + -- Handle exception in `a_file'. + end + a_file.open + a_file.put_character (c) + a_file.close + end +end + + diff --git a/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-exclusive-access.wiki b/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-exclusive-access.wiki new file mode 100644 index 00000000..b7c29ec0 --- /dev/null +++ b/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-exclusive-access.wiki @@ -0,0 +1,145 @@ +[[Property:title|Exclusive Access]] +[[Property:weight|4]] +[[Property:uuid|7f5adf71-7169-c54e-9bed-079c84aee8d3]] + +The topic of exclusive access was already briefly touched in [[Separate Calls]]. +In this chapter, we'll have a deeper look at the exclusive access guarantees given in SCOOP, and what it means in practice. + +== Reasoning Guarantees == + +In the SCOOP model, there are two very important guarantees - ''Order Preservation'' and ''Exclusive Access''. + +{{definition|Order Preservation | The guarantee that, between any two regions, the order of separate feature calls logged by one region is the same as the order of feature applications by the other region.}} +{{definition|Exclusive Access (to a region) | The guarantee that no intervening features logged by other processors are executed.}} + +The first guarantee is always valid. +A SCOOP processor is never allowed to reorder two feature calls when both have been logged by the same region. +However, the order preservation guarantee only holds between two processors - it is not valid in a global context. +For example, when a region A first logs a command to C, and then another region B logs a command to C, you generally don't know which feature will be applied first. +And also the other way around: You have no guarantee on the order of feature application when A logs both an (asynchronous) separate call to B and C. + +Exclusive access on the other hand is only valid in certain contexts. +When an object is ''controlled'', SCOOP guarantees exclusive access to the region that contains the object. +We'll define the term ''controlled'' a bit later, but you've already seen an example in [[Separate Calls]]: +A separate object which is passed as an argument. + +These two basic guarantees in the SCOOP model are important to reach one of the main goals: +The ability to reason about a program should be preserved in a concurrent program. +SCOOP guarantees that a ''controlled'' object behaves just like in a sequential program, +meaning that Pre- and Postconditions will remain valid in between feature calls because no other processor can interfere. + +== Inline Separate == + +Passing a separate object as an argument is not the only way to gain exclusive access in SCOOP. +While in theory the mechanism would be sufficient, experience has shown that it's often bulky and not very elegant to write a new routine whenever one wants to call a feature on a separate target. + +Therefore SCOOP introduces the ''Inline Separate'' block to make things a bit easier. + +person: separate PERSON + +show_separate_block + do + separate person as l_person do + print (l_person.age) + end + end + + +The separate block evaluates the expression on the left hand side of the as keyword, assigns it to the new read-only local variable l_person on the right hand side, +and does whatever is necessary to provide ''exclusive access'' to the region that handles l_person. + +You can think of the inline separate block as syntactic sugar that creates a new wrapper routine (although inline separate still lets you access local variables of the enclosing routine): + +person: separate PERSON + +show_separate_block + do + anonymous_wrapper (person) + end + +anonymous_wrapper (l_person: separate PERSON) + do + print (l_person.age) + end + + +== Controlled Objects == + +The Eiffel compiler introduces the concept of a ''controlled'' object to support the exclusive access guarantee. + +{{definition|Controlled/uncontrolled object|An object is '''controlled''' if it is attached to a reference that has one of the following properties:
+1) It is of a non-separate type.
+2) It is of a separate type and it appears as a formal argument of the enclosing routine.
+3) It is a local variable of an inline separate block. +

Otherwise it is '''uncontrolled'''.}} + +An object is always ''controlled'' with respect to the processor handling Current, and the meaning is that the current processor has ''Exclusive Access'' to the region that holds the object. In particular, this means that no other processor can access or modify a controlled object. + +In chapter [[Separate Calls]] we've already mentioned that SCOOP places a restriction on separate calls. +A separate call is allowed if the target appears as a formal argument of the enclosing routine. +While this rule is correct, it does not cover all of the cases. +With the above definition however, we can both simplify and extend the previous ''Separate Argument'' rule: + +{{rule|name=Controlled Target|text=A separate call is valid if its target is controlled.}} + +The compiler checks this property at compile-time and throws an error if a separate call happens on an uncontrolled target. + +{{note| Query results with a non-separate return type are placed on the same processor as the target. This means that, if a processor controls the target, it is also safe to use these query results. The compiler tries to exploit this fact a little by treating such query results as controlled as well within a single expression. This allows to have multi-dot calls on separate target, such as sep_person.spouse.name.out.
+Note that this does not yet cover all cases where ''controlled'' can be inferred, and the compiler may become smarter in the future.}} + +== Exclusive Access to multiple regions == + +It is possible to gain exclusive access to multiple regions simultaneously. +This can either be done by passing multiple arguments to a region, or with an ''inline separate'' block. + + +balance_with_arguments (incr: separate INCREMENTER; decr: separate DECREMENTER): INTEGER + do + Result := incr.value + decr.value + end + +balance_with_inline_separate: INTEGER + do + separate incrementer as incr, decrementer as decr do + Result := incr.value + decr.value + end + end + +incrementer: separate INCREMENTER +decrementer: separate DECREMENTER + + +Exclusive access to the arguments is granted '''atomically''' in this case. +This ensures that no deadlock can occur when two regions want to gain access to the same regions, provided that they both use the "multiple-arguments-mechanism" of SCOOP and don't lock regions one after the other by hand. + +{{SeeAlso|The dining philosopher example makes use of this fact. The feature {PHILOSOPHER}.eat has two separate arguments, which are guaranteed to be locked in one atomic step by the SCOOP runtime. If this were not the case, a deadlock may occur.}} + +== Waiting for regions == + +You may wonder how the exclusive access guarantee is implemented in SCOOP. +A simple solution would be to have a lock for every region, and to gain exclusive access, one has to acquire the lock. +Before the 15.01 release, this was indeed how it was implemented. +However, the implementation proved to be flawed because it caused a lot of synchronization and waiting. + +In EiffelStudio 15.01 this has changed. +When a processor needs exclusive access to another one, it opens a new ''queue'' to log calls. +There can be multiple open queues to a processor, but the processor will always work on only one queue. + +This has an important effect in practice: '''Gaining exclusive access to a region is always non-blocking.''' +Note that this is also true for exclusive access to multiple regions. +Previously it may have been necessary to wait for another processor to relinquish the lock, but now a processor can just proceed with logging calls, which will eventually be executed by the supplier processor. + +You may start to wonder now where waiting happens, as it isn't possible to both have a guarantee for exclusive access and fully non-blocking behaviour. +Well, it happens during synchronous calls. +When a client gains exclusive access and starts logging calls, the supplier may not care about it yet because it is busy with something else. +However, as soon as a synchronous call is logged, the client needs to wait for the result. +During that time, the supplier will finish its other tasks and eventually start to execute the calls logged by the suspended client, at which point it will wake up again. + +{{note|Due to this, the only way to experience a deadlock in SCOOP is when a processor is stuck in a separate query.}} + +To summarize: +* Gaining exclusive access, also to multiple regions, is always non-blocking. +* An asynchronous call is also non-blocking. +* Only a call to a query may be blocking, and thus a place where a processor can be stuck (e.g. in case of deadlock or starvation). + + diff --git a/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-getting-started.wiki b/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-getting-started.wiki new file mode 100644 index 00000000..46f384cb --- /dev/null +++ b/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-getting-started.wiki @@ -0,0 +1,74 @@ +[[Property:title|Getting Started with SCOOP]] +[[Property:link_title|Getting Started]] +[[Property:weight|-1]] +[[Property:uuid|87f78898-2bbb-b134-0128-e55401a61a05]] +=Introduction= + +SCOOP adds only a single keyword to the Eiffel programming language: separate. In any case in which SCOOP is not enabled, the separate keyword is ignored, and the SCOOP-specific validity rules are not applied. + +In order to enable SCOOP processing in your project, you use the project settings. There are two mandatory settings. One of them is the option ''Concurrency'', and the value you need is ''SCOOP'', as shown in the section of the Project Settings dialog below. + +[[Image:SCOOP project setting]] + +The second setting is the precompiled library. This should either be '''base-scoop-safe''', or nothing at all. A precompiled library which is not built with SCOOP support will not work. + +{{caution | When you use a precompiled library, the ''Concurrency'' setting for that library trumps whatever ''Concurrency'' value you have set for the project. So, if you use the "base-safe.ecf" precompiled library, your project will not be SCOOP-enabled regardless of the setting of ''Concurrency'' in the Target. Likewise, using the "base-scoop-safe.ecf" precompiled library always produces a SCOOP-enabled project, even if the Target ''Concurrency'' setting is ''No concurrency''.}} + + +=Creating a new SCOOP project= + +== Step 1: Create a new project == + +Create a new project with the EiffelStudio new project wizard by selecting ''Basic application'' from the choices under ''Create project'' when EiffelStudio opens. +The created project will not have SCOOP enabled however (this is true in all EiffelStudio releases so far, but may change in the future). +Do not compile the newly created project or precompile a library if asked - it will just be a waste of time. + +== Step 2: Convert the project == + +To enable SCOOP, you'll have to do some work on the project settings. Follow the steps in the next section. + += Convert an existing project to SCOOP = + +== Step 1: Adjust Concurrency setting == + +Open the project settings dialogue (Project -> Project settings...). +Select your favourite target (usually there's only one) and extend the section ''Advanced''. + +In there you'll find the setting ''Concurrency'', which should have a value ''No concurrency'' for sequential projects. Change it to ''SCOOP''. + +In addition to the ''Concurrency'' project setting, it is recommended that for new projects you use [[Creating a new void-safe project#Project settings for void-safe projects|the settings that guarantee void-safety]]. + +== Step 2: Remove the precompiled library == + +Expand the node ''Groups'' in the project settings on the left. +If your project uses a precompiled library, you should be able to see and expand the node ''Precompile'' as well. +Right click on the item (usually something like "base-safe_precompile") in the category ''Precompile'', then select ''Remove''. + +== Step 3: (Optional) Add precompiled base-scoop-safe to the project == + +Select the node ''Groups'' on the left, and then press Ctrl + P on the keyboard (or select ''Add Precompile'' from the toolbox). +Note that this only works when there's no existing precompiled library and when the node ''Groups'' is highlighted. + +In the dialog that opens, select "precomp_base-scoop-safe", then close the dialog by clicking ''OK''. + +== Step 4: Clean compile == + +Changing the ''Concurrency'' setting and precompiled libraries each would cause you to have to do a [[Clean compile|clean compile]] of your system in order to become effective. To do so, close EiffelStudio and reopen it. +In the dialog that appears, select the previously modified project and then select the ''Compile'' action and add a tick to ''Clean''. +At this point, your project should be void-safe and SCOOP enabled. + +== Step 5: Double-check == + +Before doing anything after the clean compile, check the warnings section. If EiffelStudio is complaining that some settings could not be applied, something might be wrong with the precompiled library. + +To make sure that SCOOP is really enabled, you can insert the following code snippet somewhere in your code: + +check_scoop (a_string: separate STRING) + local + str: STRING + do + str := a_string + end + +This should trigger a compiler error. If it doesn't, then SCOOP is not correctly set up in your project. + diff --git a/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-implementation.wiki b/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-implementation.wiki index a7384114..a1b922f0 100644 --- a/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-implementation.wiki +++ b/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-implementation.wiki @@ -1,5 +1,5 @@ [[Property:title|SCOOP implementation]] -[[Property:weight|2]] +[[Property:weight|9]] [[Property:uuid|eeb07907-e036-f3d6-5297-a7c44cfd1900]] The implementation of SCOOP within EiffelStudio varies from the definition as it has been presented in publications during the model's evolution. @@ -60,7 +60,7 @@ In version 6.8, agents targeted on separate objects are not supported. The first implementation of SCOOP, some things that we do commonly in sequential Eiffel become less fluid in the presence of SCOOP. Although not strictly limitations in the implementation of SCOOP principles, in order to make SCOOP programming easier, these are areas that should be improved in future releases. In the meantime, there are workarounds for some of these situations. -==Printing a separate STRING == +==Printing a separate STRING == Suppose you have declared a class attribute of type separate STRING: @@ -94,16 +94,46 @@ Or use a creation expression and avoid declaring the local variable: io.put_string (create {STRING}.make_from_separate (my_separate_string)) +== Calling a separate agent == + +Calling a separate agent is a bit tricky, especially if it's a PROCEDURE which should be executed asynchronously. +If the agent does not take any arguments, you must pass Void, otherwise the compiler will generate an empty TUPLE which +is on the same processor as the caller and thus triggers lock passing (see [[Asynchronous Calls]]): + + +do_call (proc: separate PROCEDURE [ANY, TUPLE]) + do + proc.call (Void) + end + + +If the agent does take arguments, things get a bit more tricky. If the call must be asynchronous, you have to do a workaround with the feature {ROUTINE}.empty_operands like this: + + +do_call (a_procedure: separate PROCEDURE [ANY, TUPLE[separate STRING]]; a_string: separate STRING) + local + l_tuple: separate TUPLE [separate STRING] + do + l_tuple := a_procedure.empty_operands + set_tuple_string (l_tuple, a_string) + a_procedure.call (l_tuple) + end + +set_tuple_string (a_tuple: separate TUPLE [str: separate STRING]; a_string: separate STRING) + do + a_tuple.str := a_string + end + + =Implementation dependent behavior= ==The Wait Rule== +{{note | This only applies to EiffelStudio releases prior to 15.01}} + The [[Concurrent Eiffel with SCOOP#Access to shared resources|Wait Rule]] says: ''A routine call with separate arguments will execute when all corresponding processors are available and hold them exclusively for the duration of the routine.'' -In the EiffelStudio implementation, a routine will not necessarily wait for all processors associated with its separate arguments to be available before it ''begins'' execution. The waiting on processors occurs in a "lazy" manner. Execution will only wait on the availability of one of the processors when it actually needs to use the argument associated with that processor. This means that if there are several instructions ahead of the first instruction that references a separate argument, then those several instructions will be executed immediately. Only at the point at which the separate argument's processor is needed will the routine pause and wait for the availability of the processor. - - - +In the EiffelStudio implementation prior to 15.01, a routine will not necessarily wait for all processors associated with its separate arguments to be available before it ''begins'' execution. The waiting on processors occurs in a "lazy" manner. Execution will only wait on the availability of one of the processors when it actually needs to use the argument associated with that processor. This means that if there are several instructions ahead of the first instruction that references a separate argument, then those several instructions will be executed immediately. Only at the point at which the separate argument's processor is needed will the routine pause and wait for the availability of the processor. diff --git a/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-practical-matters.wiki b/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-practical-matters.wiki deleted file mode 100644 index cde22c82..00000000 --- a/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-practical-matters.wiki +++ /dev/null @@ -1,52 +0,0 @@ -[[Property:title|SCOOP practical matters]] -[[Property:weight|-1]] -[[Property:uuid|87f78898-2bbb-b134-0128-e55401a61a05]] -=Introduction= - -''SCOOP practical matters'' is a collection of advice for using SCOOP effectively. Here you will find practical information that supplements the rules and definitions of the basic [[Concurrent Eiffel with SCOOP|SCOOP model]], or that is unique to the implementation of SCOOP in EiffelStudio. - -=SCOOP project settings= - -SCOOP adds only a single keyword to the Eiffel programming language: separate. In any case in which SCOOP is not enabled, the separate keyword is ignored, and the SCOOP-specific validity rules are not applied. - -In order to enable SCOOP processing in your project, you use the project settings. Actually, there's just one mandatory setting: ''Concurrency'', and the value you need is ''SCOOP'', as shown in the section of the Project Settings dialog below. Still, in addition to the ''Concurrency'' project setting, remember that it is recommended that for new projects you use [[Creating a new void-safe project#Project settings for void-safe projects|the settings that guarantee void-safety]]. - - - -[[Image: SCOOP project setting]] - - - -{{note|The ''Concurrency'' setting requires a [[Clean compile|clean compile]] to be done in order for a change of value to take effect. }} - - -==A SCOOP project from the new project wizard== - -If you create a project using the EiffelStudio new project wizard (for example, selecting "Basic application" from the choices under "Create project" when EiffelStudio opens), the created project will have neither void-safety nor SCOOP enabled. [This is true in EiffelStudio versions 6.8 and 7.0, but may change in future versions.] So, to enable void-safety and SCOOP in such a default project, you'll have to do some work on the project settings. - -===Void-safety settings=== - -As mentioned above, you'll need to enable the [[Creating a new void-safe project#Project settings for void-safe projects|the settings that guarantee void-safety]]. - -===Libraries and precompiled libraries=== - -Notice in the note in [[Creating a new void-safe project#Project settings for void-safe projects|that section of the documentation]], that for a period of transition, you should select the "''libraryname''-safe.ecf" version of libraries for void-safe projects. There is no special SCOOP version of libraries, so if you are not using a precompiled library, then selecting "base-safe.ecf" should be sufficient. - -However, there is a special version of the precompiled EiffelBase library for SCOOP. So, if you are using precompiled EiffelBase, you should remove the precompile that the wizard included, and add the precompile with file name "base-scoop-safe.ecf". - - -{{note|When you use a precompiled library, the ''Concurrency'' setting for that library trumps whatever ''Concurrency'' value you have set for the project. So, if you use the "base-safe.ecf" precompiled library, your project will not be SCOOP-enabled regardless of the setting of ''Concurrency'' in the Target. Likewise, using the "base-scoop-safe.ecf" precompiled library always produces a SCOOP-enabled project, even if the Target ''Concurrency'' setting is ''No concurrency''.}} - - -===The SCOOP Concurrency setting=== - -Then, you should select ''SCOOP'' as a value for the ''Concurrency'' setting for your project. - -===Clean compile=== - -Changing the ''Concurrency'' setting, the ''Void-safety'' setting, and precompiled libraries each would cause you to have to do a [[Clean compile|clean compile]] of your system in order to become effective. So, next you should do a clean compile. At this point, your project should be void-safe and SCOOP enabled. - - - - - diff --git a/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-regions-processors.wiki b/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-regions-processors.wiki new file mode 100644 index 00000000..eac8d1b8 --- /dev/null +++ b/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-regions-processors.wiki @@ -0,0 +1,114 @@ +[[Property:title|Regions and Processors]] +[[Property:weight|2]] +[[Property:uuid|974a41dd-0e36-4d75-edd1-ead6ea4b372d]] +== Regions == + +One of the key ideas in SCOOP is to prohibit simultaneous access to shared memory. +In order to reach this goal, the SCOOP model partitions the heap memory into ''regions''. + +{{definition|Region|A set of objects in the heap. The set of all regions in a program is a partition of the heap.}} + +Every object in an Eiffel program belongs to exactly one ''region''. +A ''region'' is by itself sequential, meaning that there can only be one routine executed in one object. +There can be multiple regions in a SCOOP program however. + +[[Image:SCOOP regions]] + +{{info|SCOOP is classified as a message passing concurrency model, because there is no shared memory.}} +{{note|A sequential program is a special case for a SCOOP program that has only one region.}} + +A direct access from one region into another is not allowed. +If one wishes to perform a command or a query in an object of a different region, a message has to be sent. +You'll see how this can be done in chapter [[Separate Calls]]. + +The simple trick of splitting the heap into several regions, where each region by itself is sequential, +prevents one of the trickiest problems in concurrency: Data Races. +In SCOOP you are guaranteed that a data race, meaning a read and write access to the same memory with nondeterministic ordering, can never happen. + +== Processors == + +In the SCOOP model, a ''processor'' is used as the engine for execution. + +{{definition|Processor| An autonomous thread of control capable of sequential execution of instructions.}} + +A ''processor'' is always attached to exactly one region, and is responsible to perform operations on all its objects. +The term ''handler of an object'' is used to denote the processor attached to the region on which the object is placed. + +As already mentioned earlier, a ''processor'' cannot access or perform operations on an object in a different ''region'' +and has to send a message to the other handler instead. + +{{info|''Processor'' is an abstract notion and does not mean the physical silicone chip which is present in every computer. +In SCOOP we think of it as a thread of control capable of applying features to objects. +In theory processors are not restricted to any particular type of hardware or software, for example they could correspond to threads, processes, hardware processors, or machines in a network. +Currently however a SCOOP processor is implemented as a thread.}} + +== Separate Types== + +To support the concept of regions in a program text, SCOOP extends the type system by introducing a single new keyword: separate. +The separate keyword is used to annotate a reference and means that the object attached to it may be in a different region. + +{{definition|Separate type|A type which has been declared including the keyword separate.}} + +If an entity uses the keyword separate in its declaration, such as: + + + my_x: separate X + + +it indicates that the handler of my_x may be different than the handler of Current. +This in turn means that it is forbidden to access and modify my_x directly. +To perform any operation on my_x, a message should be sent to the other handler. + +Note that the SCOOP type system allows to attach an object to a separate reference, even if it is actually in the same region as Current. +But it is not possible the other way around: An object in a different region must always be of a separate type. +This is reflected in the type checker, which treats a regular type A as a subtype of the separate type separate A. + +In the image above, the three references that cross a processor boundary must be declared separate. +The single reference in Region 2, which stays in the same region, can be of a non-separate type. + +== Creating regions and processors == + +In order to turn a sequential program into a concurrent program, one has to create new regions and put objects into them. +The means to achieve this is the creation instruction on an entity whose type is separate. + + + my_x: separate X + -- ... + create my_x.make + + +The instruction create my_x.make does a lot of things at the same time: +* It creates a new region. +* It creates a new processor for the new region. +* It creates a new object of type X which is placed into the newly created region. + +With this new knowledge we can create a small program that generates the object and region graph shown above: + + +class APPLICATION create make feature + + person: separate PERSON + + thing: separate ANY + + make + do + create person.make + create thing + end +end + +class PERSON create make feature + + name: STRING + + thing: separate ANY + + make + do + create name.make_from_string ("John Doe") + create thing + end +end + + diff --git a/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-separate-calls.wiki b/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-separate-calls.wiki new file mode 100644 index 00000000..a3e9b049 --- /dev/null +++ b/documentation/current/solutions/concurrent-computing/concurrent-eiffel-scoop/scoop-separate-calls.wiki @@ -0,0 +1,126 @@ +[[Property:title|Separate Calls]] +[[Property:weight|3]] +[[Property:uuid|c030d521-1420-1570-b63e-9035332a3e26]] +==Separate Calls== + +In the [[Regions and Processors | previous chapter]] we've learned that a concurrent SCOOP program consists of several ''regions'' that communicate via message passing. +You may wonder how it is possible to pass a message to another processor, and the answer is simple: +With the good old feature call. + +{{definition|Separate call|A feature call whose target is of a separate type.}} + +The ''separate call'' is the SCOOP way to pass messages from one region to another. +A call such as this + + + do_call (my_x: separate X) + do + my_x.f (42) + end + + +roughly corresponds to a message to the handler of my_x with the content: +"Execute feature f on target my_x with argument 42." + +Note that there can be a difference between the time a message is sent and the time the feature is executed. +In SCOOP we therefore distinguish between a ''feature call'' and a ''feature application''. + +{{definition|Feature call|Register a feature to be executed.}} +{{definition|Feature application|Execute a feature.}} + + +==Access to shared resources== + +The main issue with concurrent systems is the proper control of access to resources that can be shared among simultaneously executing processors. + +Traditional solutions to the problem involve the use of “critical sections” of code. +These are sections of code in which the shared resource is accessed. +Only one thread is allowed to be executing the critical section at a time. +So if one thread wants to execute the critical section and another is already doing so, then the first must wait. +Thread synchronization schemes ensure this “mutual exclusion” of access to the critical section. + +Rather than using critical sections, SCOOP relies on the mechanism of argument passing to assure exclusive access. +As a result, there is a restriction placed on separate calls. + +{{Rule|name=Separate argument|text=A separate call a_x.f (a) is valid if a_x is an argument of the enclosing routine.}} + +So, according to this rule, for a separate call to be valid, the target of the call must be a formal argument of the routine in which the call occurs. +The code below contains both an invalid separate call and a valid one. + + + + my_separate_attribute: separate SOME_TYPE + + ... + calling_routine + -- One routine + do + my_separate_attribute.some_feature -- Invalid call: Feature call on separate attribute + enclosing_routine (my_separate_attribute) -- Separate attribute passed as argument + end + + enclosing_routine (a_arg: separate SOME_TYPE) + -- Another routine + do + a_arg.some_feature -- Valid call: Feature call on separate argument + end + + + +In the code above, my_separate_attribute is a class attribute declared as a separate type. In the first line in calling_routine a direct feature call is made to apply some_feature to my_separate_attribute. This is an invalid separate call. The second line calls feature enclosing_routine and passes my_separate_attribute as an argument. enclosing_routine takes an argument of type separate SOME_TYPE. Within enclosing_routine it is valid to call some_feature on a_arg. + +{{info|Congratulations! You've just gained enough knowledge to write a small SCOOP program. +You may want to have a look at the [[Dining Philosophers]] example, which does not use any of the advanced concepts.}} + +{{SeeAlso|The launch_producer feature of the [[Producer-consumer|producer-consumer]] example, a feature which exists for the purpose of compliance with the separate argument rule.}} + + +==Synchronous and asynchronous feature calls== + +When we think of the execution of sequential Eiffel, we tend to equate feature call and feature application. That is, it is expected that for a sequence of two feature calls: + + + + x.f + y.g + + + +that the feature application of x.f will complete before y.g begins. + +In concurrent Eiffel with SCOOP things are different. This is because a particular feature call, x.f, may occur on one processor, and the consequent feature application (of feature f to x) may occur on a different processor. + + +{{definition|Synchronous feature call|A feature call in which the execution of the calling client does not proceed until the feature application has completed. }} + + +{{definition|Asynchronous feature call|A feature call which causes the “logging” of a request by a client for the associated feature application to be executed by the supplier’s processor. }} + + +After an asynchronous feature call, the execution of the client proceeds immediately, possibly in parallel with the application of the feature on some other processor. + + +===What makes a call synchronous or asynchronous?=== + +First, every feature call is either a synchronous feature call or an asynchronous feature call. For a particular call, the following rules determine which it is: + +A feature call is always '''synchronous''' in the following cases: + +:S1 It is a non-separate call. +:S2 It is a separate call to a query. + +A feature call may be '''asynchronous''' in the following case: +:A1 It is a separate call to a command. + +Let’s look a little closer at those cases determining synchronous calls. + +Case S1 is the case of typical sequential Eiffel, where all calls are non-separate, and therefore synchronous. Of course, even in concurrent Eiffel with SCOOP, plenty of non-separate calls will occur, and these will be synchronous. + +Case S2 says that if a separate call is a query it must be synchronous. This is because even though the feature application will probably occur on a different processor, the instructions following the query will likely depend up on the result of the query, so they must wait until the feature application completes. This situation is known as ''wait by necessity''. + +The case A1 is the only case where asynchrony is involved. But be careful with the wording - it says the call '''may be asynchronous''', because there are some exceptions. The exact rules are a bit complex and are described in [[Asynchronous Calls]]. As a general rule of thumb, a separate call is executed asynchronously when the client does not have exclusive access over an object which is needed by the target region. + +Asynchronous execution means that when a client processes the call to the command, it “logs” the need for its associated feature application. But then, rather than waiting for the feature application to complete, the client continues execution of instructions beyond the asynchronous call. + +It is in this case that concurrent computation is achieved. The processor of the client object is free to continue processing while the processor handling the target of the asynchronous feature call applies that feature. +