summaryrefslogtreecommitdiffstats
path: root/Dispatcher.st
blob: 0442512a874a79c994fcb385e73a67a4ea76b370 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
"
 (C) 2011 by Holger Hans Peter Freyther
 All Rights Reserved

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU Affero General Public License as
 published by the Free Software Foundation, either version 3 of the
 License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Affero General Public License for more details.

 You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
"

Object subclass: Dispatcher [
    | queue dispatch quit |
    <category: 'OsmoCore-Core'>
    <comment: 'I run tasks from the same context.'>

    Dispatcher class >> instance [
        <category: 'singleton'>
        ^ Smalltalk at: #OsmoDispatcher ifAbsent: [self install].
    ]

    Dispatcher class >> new [
        <category: 'private'>
        ^super new
            addToBeFinalized;
            startDispatching;
            yourself
    ]

    Dispatcher class >> install [
        <category: 'singleton'>
        | dispatcher |
        dispatcher := Smalltalk at: #OsmoDispatcher ifAbsentPut: [self new].
        ^dispatcher class = self
            ifTrue: [dispatcher]
            ifFalse: [
                dispatcher terminate.
                Smalltalk at: #OsmoDispatcher put: self new]
    ]

    startDispatching [
        <category: 'private'>
        quit := false.
        queue := SharedQueue new.
        dispatch := [
            Processor activeProcess name: 'OsmoDispatcher'.
	    [quit]
              whileFalse: [
                self dispatch]
          ] forkAt: Processor highIOPriority.
    ]

    dispatchBlock: aBlock [
        <category: 'insert'>
        queue nextPut: aBlock.
    ]

    dispatch [
        | block sem |
        block := queue next.
        sem := Semaphore new.

        "Run the code in a new process as the debugger might terminate this
        and then the dispatcher would not dispatch anymore. Use a Semaphore
        to make sure we keep on processing items in order."
        [[
        block on: Error do: [:error |
            error logException: ('dispatch failed on "', block printString, '".') area: #core.
        ]] ensure: [sem signal]] fork.

        sem wait.
    ]   

    terminate [
        <category: 'private'>
        dispatch terminate
    ]
]

Eval [
    Dispatcher instance.
]