copland 0.8.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/doc/manual-html/chapter-1.html +227 -36
- data/doc/manual-html/chapter-10.html +155 -82
- data/doc/manual-html/chapter-11.html +90 -267
- data/doc/manual-html/chapter-12.html +289 -71
- data/doc/manual-html/chapter-13.html +430 -0
- data/doc/manual-html/chapter-2.html +45 -21
- data/doc/manual-html/chapter-3.html +45 -21
- data/doc/manual-html/chapter-4.html +45 -21
- data/doc/manual-html/chapter-5.html +45 -21
- data/doc/manual-html/chapter-6.html +49 -21
- data/doc/manual-html/chapter-7.html +45 -21
- data/doc/manual-html/chapter-8.html +66 -26
- data/doc/manual-html/chapter-9.html +48 -24
- data/doc/manual-html/index.html +54 -22
- data/doc/manual-html/manual.css +12 -0
- data/doc/manual-html/tutorial-1.html +45 -21
- data/doc/manual-html/tutorial-2.html +45 -21
- data/doc/manual-html/tutorial-3.html +45 -21
- data/doc/manual-html/tutorial-4.html +45 -21
- data/doc/manual-html/tutorial-5.html +45 -21
- data/doc/manual/manual.css +12 -0
- data/doc/manual/manual.rb +1 -1
- data/doc/manual/manual.yml +426 -20
- data/doc/packages/copland.html +41 -9
- data/doc/packages/copland.lib.html +36 -8
- data/doc/packages/copland.remote.html +46 -10
- data/doc/packages/copland.webrick.html +16 -65
- data/doc/packages/index.html +1 -1
- data/doc/presentation/copland.mgp +1083 -0
- data/doc/presentation/to_html.rb +52 -0
- data/lib/copland/configuration-point/common.rb +32 -1
- data/lib/copland/configuration/yaml/service-point.rb +10 -1
- data/lib/copland/log-factory.rb +28 -12
- data/lib/copland/logger.rb +155 -0
- data/lib/copland/models/singleton.rb +8 -2
- data/lib/copland/package.rb +32 -14
- data/lib/copland/service-point.rb +7 -0
- data/lib/copland/thread.rb +104 -0
- data/lib/copland/utils.rb +10 -3
- data/lib/copland/version.rb +2 -2
- data/test/configuration/yaml/tc_service-point-processor.rb +8 -0
- data/test/custom-logger.yml +2 -1
- data/test/impl/tc_logging-interceptor.rb +12 -12
- data/test/logger.yml +1 -1
- data/test/mock.rb +2 -0
- data/test/tc_logger.rb +19 -6
- data/test/tc_package.rb +25 -0
- data/test/tc_queryable-mutex.rb +75 -0
- data/test/tc_registry.rb +8 -4
- metadata +9 -2
@@ -88,6 +88,12 @@ module Copland
|
|
88
88
|
# passed to the factory when a new instance is required.
|
89
89
|
attr_accessor :schema
|
90
90
|
|
91
|
+
# The visibility of this service point. If <tt>:public</tt> (the default),
|
92
|
+
# the service point is accessible outside of its package. If it is
|
93
|
+
# <tt>:private</tt>, then it is only directly accessible to other services
|
94
|
+
# within its package.
|
95
|
+
attr_accessor :visibility
|
96
|
+
|
91
97
|
# Create a new service point, contained by the +owner+ package. The only
|
92
98
|
# recognized option currently is <tt>:default_service_model</tt>, which
|
93
99
|
# is used to identify the service model to use when no other service model
|
@@ -95,6 +101,7 @@ module Copland
|
|
95
101
|
def initialize( owner, name, opts={} )
|
96
102
|
@owner = owner
|
97
103
|
@name = name
|
104
|
+
@visibility = :public
|
98
105
|
|
99
106
|
use_service_model opts[ :default_service_model ] || DEFAULT_SERVICE_MODEL
|
100
107
|
|
@@ -0,0 +1,104 @@
|
|
1
|
+
#--
|
2
|
+
# =============================================================================
|
3
|
+
# Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
|
4
|
+
# All rights reserved.
|
5
|
+
#
|
6
|
+
# Redistribution and use in source and binary forms, with or without
|
7
|
+
# modification, are permitted provided that the following conditions are met:
|
8
|
+
#
|
9
|
+
# * Redistributions of source code must retain the above copyright notice,
|
10
|
+
# this list of conditions and the following disclaimer.
|
11
|
+
#
|
12
|
+
# * Redistributions in binary form must reproduce the above copyright
|
13
|
+
# notice, this list of conditions and the following disclaimer in the
|
14
|
+
# documentation and/or other materials provided with the distribution.
|
15
|
+
#
|
16
|
+
# * The names of its contributors may not be used to endorse or promote
|
17
|
+
# products derived from this software without specific prior written
|
18
|
+
# permission.
|
19
|
+
#
|
20
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
21
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
22
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
23
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
24
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
25
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
26
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
27
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
28
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
29
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
30
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
31
|
+
# =============================================================================
|
32
|
+
#++
|
33
|
+
|
34
|
+
require 'thread'
|
35
|
+
|
36
|
+
module Copland
|
37
|
+
|
38
|
+
# A subclass of Mutex that allows clients to discover which thread has the
|
39
|
+
# mutex locked. This is necessary for (among other things) discovering
|
40
|
+
# cycles in the dependency graph of services.
|
41
|
+
class QueryableMutex < Mutex
|
42
|
+
|
43
|
+
# Checks to see if the current thread has the mutex locked, and if it
|
44
|
+
# does, raises an exception. Otherwise, locks the mutex and sets the
|
45
|
+
# locking thread to Thread.current.
|
46
|
+
def lock
|
47
|
+
if @locking_thread == Thread.current
|
48
|
+
raise ThreadError,
|
49
|
+
"an attempt was made to reacquire an existing lock " +
|
50
|
+
"(this could happen if you have a circular dependency on a service)"
|
51
|
+
end
|
52
|
+
|
53
|
+
while (Thread.critical = true; @locked)
|
54
|
+
@waiting.push Thread.current
|
55
|
+
Thread.stop
|
56
|
+
end
|
57
|
+
@locked = true
|
58
|
+
@locking_thread = Thread.current
|
59
|
+
Thread.critical = false
|
60
|
+
self
|
61
|
+
end
|
62
|
+
|
63
|
+
# Attempts to acquire the lock. Returns +true+ if the lock was acquired,
|
64
|
+
# and +false+ if the mutex was already locked.
|
65
|
+
def try_lock
|
66
|
+
result = false
|
67
|
+
Thread.critical = true
|
68
|
+
unless @locked
|
69
|
+
@locked = true
|
70
|
+
result = true
|
71
|
+
@locking_thread = Thread.current
|
72
|
+
end
|
73
|
+
Thread.critical = false
|
74
|
+
result
|
75
|
+
end
|
76
|
+
|
77
|
+
# Unlocks the mutex and sets the locking thread to +nil+.
|
78
|
+
def unlock
|
79
|
+
return unless @locked
|
80
|
+
Thread.critical = true
|
81
|
+
@locked = false
|
82
|
+
begin
|
83
|
+
t = @waiting.shift
|
84
|
+
t.wakeup if t
|
85
|
+
rescue ThreadError
|
86
|
+
retry
|
87
|
+
end
|
88
|
+
@locking_thread = nil
|
89
|
+
Thread.critical = false
|
90
|
+
begin
|
91
|
+
t.run if t
|
92
|
+
rescue ThreadError
|
93
|
+
end
|
94
|
+
self
|
95
|
+
end
|
96
|
+
|
97
|
+
# Return +true+ if the current thread has locked this mutex.
|
98
|
+
def self_locked?
|
99
|
+
@locking_thread == Thread.current
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
data/lib/copland/utils.rb
CHANGED
@@ -51,15 +51,19 @@ module Copland
|
|
51
51
|
# it passes the correct pkg and unqualified service name to the block and
|
52
52
|
# returns the result.
|
53
53
|
def get_possibly_local_service( registry, pkg, id )
|
54
|
+
original_package = pkg
|
55
|
+
|
54
56
|
if id =~ /^(.+)\.([^.]+)$/
|
55
57
|
pkg = registry.package( $1 )
|
56
58
|
id = $2
|
57
59
|
end
|
58
60
|
|
61
|
+
local_service = ( original_package == pkg )
|
62
|
+
|
59
63
|
if block_given?
|
60
|
-
yield pkg, id
|
64
|
+
yield pkg, id, local_service
|
61
65
|
else
|
62
|
-
pkg.service( id )
|
66
|
+
pkg.service( id, local_service )
|
63
67
|
end
|
64
68
|
end
|
65
69
|
|
@@ -121,7 +125,9 @@ module Copland
|
|
121
125
|
# real:: the value is interpreted as a floating point
|
122
126
|
# string:: the value is interpreted as a string
|
123
127
|
def translate_value( registry, pkg, point, value )
|
124
|
-
|
128
|
+
unless Thread.current[:disable_symbol_substitution]
|
129
|
+
substitute_symbols( registry, value )
|
130
|
+
end
|
125
131
|
|
126
132
|
if value.is_a?( Array )
|
127
133
|
return translate_array( registry, pkg, point, value )
|
@@ -140,6 +146,7 @@ module Copland
|
|
140
146
|
pkg.configuration_point id
|
141
147
|
end
|
142
148
|
raise ConfigurationPointNotFound, value.value unless cfg
|
149
|
+
cfg.substitute_symbols!
|
143
150
|
return cfg
|
144
151
|
when "class"
|
145
152
|
return get_class( value.value )
|
data/lib/copland/version.rb
CHANGED
@@ -81,6 +81,13 @@ class TC_ServicePointProcessor < Test::Unit::TestCase
|
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
84
|
+
def test_bad_visibility_type
|
85
|
+
assert_raise( Copland::Configuration::ParserError ) do
|
86
|
+
@processor.process "name", "implementor" => "something",
|
87
|
+
"visibility" => "blah"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
84
91
|
def test_valid
|
85
92
|
point = nil
|
86
93
|
|
@@ -91,6 +98,7 @@ class TC_ServicePointProcessor < Test::Unit::TestCase
|
|
91
98
|
"description" => "a",
|
92
99
|
"interceptors" => [],
|
93
100
|
"listen-to" => [],
|
101
|
+
"visibility" => "private",
|
94
102
|
"schema" => "mock.MockParameterProcessor"
|
95
103
|
end
|
96
104
|
|
data/test/custom-logger.yml
CHANGED
@@ -63,8 +63,8 @@ class TC_LoggingInterceptor < Test::Unit::TestCase
|
|
63
63
|
|
64
64
|
assert_equal "", @device.message
|
65
65
|
service.echo 15
|
66
|
-
assert_match(
|
67
|
-
assert_match(
|
66
|
+
assert_match( /\[DEBUG\] .* -- logging.Test: echo\( 15 \)/, @device.message )
|
67
|
+
assert_match( /\[DEBUG\] .* -- logging.Test: echo => 15/, @device.message )
|
68
68
|
end
|
69
69
|
|
70
70
|
def test_exclude
|
@@ -72,8 +72,8 @@ class TC_LoggingInterceptor < Test::Unit::TestCase
|
|
72
72
|
|
73
73
|
assert_equal "", @device.message
|
74
74
|
service.echo 15
|
75
|
-
assert_match(
|
76
|
-
assert_match(
|
75
|
+
assert_match( /\[DEBUG\] .* -- logging.TestExclude: echo\( 15 \)/, @device.message )
|
76
|
+
assert_match( /\[DEBUG\] .* -- logging.TestExclude: echo => 15/, @device.message )
|
77
77
|
|
78
78
|
@device.clear
|
79
79
|
assert_equal "", @device.message
|
@@ -91,8 +91,8 @@ class TC_LoggingInterceptor < Test::Unit::TestCase
|
|
91
91
|
|
92
92
|
assert_equal "", @device.message
|
93
93
|
service.echo 15
|
94
|
-
assert_match(
|
95
|
-
assert_match(
|
94
|
+
assert_match( /\[DEBUG\] .* -- logging.TestInclude: echo\( 15 \)/, @device.message )
|
95
|
+
assert_match( /\[DEBUG\] .* -- logging.TestInclude: echo => 15/, @device.message )
|
96
96
|
|
97
97
|
@device.clear
|
98
98
|
assert_equal "", @device.message
|
@@ -102,8 +102,8 @@ class TC_LoggingInterceptor < Test::Unit::TestCase
|
|
102
102
|
@device.clear
|
103
103
|
assert_equal "", @device.message
|
104
104
|
service.echo_notme_multiple 15, 16
|
105
|
-
assert_match(
|
106
|
-
assert_match(
|
105
|
+
assert_match( /\[DEBUG\] .* -- logging.TestInclude: echo_notme_multiple\( 15, 16 \)/, @device.message )
|
106
|
+
assert_match( /\[DEBUG\] .* -- logging.TestInclude: echo_notme_multiple => \[15, 16\]/, @device.message )
|
107
107
|
end
|
108
108
|
|
109
109
|
def test_include2
|
@@ -112,8 +112,8 @@ class TC_LoggingInterceptor < Test::Unit::TestCase
|
|
112
112
|
@device.clear
|
113
113
|
assert_equal "", @device.message
|
114
114
|
service.echo_notme 15
|
115
|
-
assert_match(
|
116
|
-
assert_match(
|
115
|
+
assert_match( /\[DEBUG\] .* -- logging.TestInclude2: echo_notme\( 15 \)/, @device.message )
|
116
|
+
assert_match( /\[DEBUG\] .* -- logging.TestInclude2: echo_notme => 15/, @device.message )
|
117
117
|
|
118
118
|
@device.clear
|
119
119
|
assert_equal "", @device.message
|
@@ -126,8 +126,8 @@ class TC_LoggingInterceptor < Test::Unit::TestCase
|
|
126
126
|
|
127
127
|
assert_equal "", @device.message
|
128
128
|
service.echo 15, 16, 17
|
129
|
-
assert_match(
|
130
|
-
assert_match(
|
129
|
+
assert_match( /\[DEBUG\] .* -- logging.TestArity: echo\( 15, 16, 17 \)/, @device.message )
|
130
|
+
assert_match( /\[DEBUG\] .* -- logging.TestArity: echo => \[15, 16, 17\]/, @device.message )
|
131
131
|
|
132
132
|
@device.clear
|
133
133
|
assert_equal "", @device.message
|
data/test/logger.yml
CHANGED
data/test/mock.rb
CHANGED
@@ -91,12 +91,14 @@ class MockServicePoint
|
|
91
91
|
|
92
92
|
attr_accessor :instantiator
|
93
93
|
attr_accessor :parameter_processor
|
94
|
+
attr_accessor :visibility
|
94
95
|
|
95
96
|
def initialize( message="" )
|
96
97
|
@message = message
|
97
98
|
@pending_interceptors = []
|
98
99
|
@event_producers = []
|
99
100
|
@listeners = []
|
101
|
+
@visibility = :public
|
100
102
|
end
|
101
103
|
|
102
104
|
def instance
|
data/test/tc_logger.rb
CHANGED
@@ -62,21 +62,21 @@ class TC_Logger < Test::Unit::TestCase
|
|
62
62
|
def test_log_config
|
63
63
|
factory = Copland::LogFactory.new
|
64
64
|
assert_equal "./sample.log", factory.device.filename
|
65
|
-
assert_equal "%Y-%m-%d %H:%M:%S", factory.
|
65
|
+
assert_equal "%Y-%m-%d %H:%M:%S", factory.default_date_format
|
66
66
|
assert_equal Logger::INFO, factory.default_level
|
67
67
|
factory.close
|
68
68
|
|
69
69
|
factory = Copland::LogFactory.new :config_file => 'custom-logger.yml'
|
70
70
|
assert_equal "./custom.log", factory.device.filename
|
71
|
-
assert_equal "date %Y-%m-%d %H:%M:%S", factory.
|
71
|
+
assert_equal "date %Y-%m-%d %H:%M:%S", factory.default_date_format
|
72
72
|
assert_equal Logger::FATAL, factory.default_level
|
73
73
|
factory.close
|
74
74
|
end
|
75
75
|
|
76
76
|
def test_log_options
|
77
|
-
factory = Copland::LogFactory.new :
|
77
|
+
factory = Copland::LogFactory.new :default_date_format => "%Y",
|
78
78
|
:default_level => Logger::FATAL
|
79
|
-
assert_equal "%Y", factory.
|
79
|
+
assert_equal "%Y", factory.default_date_format
|
80
80
|
assert_equal Logger::FATAL, factory.default_level
|
81
81
|
factory.close
|
82
82
|
end
|
@@ -105,7 +105,7 @@ class TC_Logger < Test::Unit::TestCase
|
|
105
105
|
assert_equal "", io.message
|
106
106
|
|
107
107
|
log.info "test"
|
108
|
-
assert_match(
|
108
|
+
assert_match( /\[INFO \] .* -- test.log1: test/, io.message )
|
109
109
|
|
110
110
|
factory.close
|
111
111
|
assert_equal "<closed>", io.message
|
@@ -123,9 +123,22 @@ class TC_Logger < Test::Unit::TestCase
|
|
123
123
|
log = factory.get( "level.test.log1" )
|
124
124
|
|
125
125
|
log.debug "test"
|
126
|
-
assert_match(
|
126
|
+
assert_match( /\[DEBUG\] .* -- level.test.log1: test/, io.message )
|
127
127
|
|
128
128
|
factory.close
|
129
129
|
end
|
130
130
|
|
131
|
+
def test_message_format
|
132
|
+
io = MockLogIO.new
|
133
|
+
factory = Copland::LogFactory.new :device => io,
|
134
|
+
:default_message_format => "%c %C [%-5p] %F %m %M %t %% %$"
|
135
|
+
|
136
|
+
log = factory.get( "message.log1" )
|
137
|
+
log.info "test"
|
138
|
+
assert_match(
|
139
|
+
/log1 message.log1 \[INFO \] \S*tc_logger.rb test test_message_format #{Thread.current.__id__} % #{$$}\n/,
|
140
|
+
io.message
|
141
|
+
)
|
142
|
+
end
|
143
|
+
|
131
144
|
end
|
data/test/tc_package.rb
CHANGED
@@ -121,6 +121,31 @@ class TC_Package < Test::Unit::TestCase
|
|
121
121
|
end
|
122
122
|
end
|
123
123
|
|
124
|
+
def test_public_private
|
125
|
+
assert_equal 0, @package.service_points.length
|
126
|
+
|
127
|
+
point = MockServicePoint.new
|
128
|
+
point.visibility = :private
|
129
|
+
@package.add_service_point point
|
130
|
+
|
131
|
+
assert_equal 0, @package.service_point_count
|
132
|
+
assert_equal 1, @package.service_point_count(true)
|
133
|
+
|
134
|
+
assert_equal 0, @package.service_points.length
|
135
|
+
assert_equal 1, @package.service_points(true).length
|
136
|
+
|
137
|
+
assert_nil @package.service_point( "point" )
|
138
|
+
assert_not_nil @package.service_point( "point", true )
|
139
|
+
|
140
|
+
assert_raise( Copland::ServicePointNotFound ) do
|
141
|
+
@package.service( "point" )
|
142
|
+
end
|
143
|
+
|
144
|
+
assert_nothing_raised do
|
145
|
+
@package.service( "point", true )
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
124
149
|
def test_configuration_points
|
125
150
|
assert_equal 0, @package.configuration_points.length
|
126
151
|
|
@@ -0,0 +1,75 @@
|
|
1
|
+
#--
|
2
|
+
# =============================================================================
|
3
|
+
# Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
|
4
|
+
# All rights reserved.
|
5
|
+
#
|
6
|
+
# Redistribution and use in source and binary forms, with or without
|
7
|
+
# modification, are permitted provided that the following conditions are met:
|
8
|
+
#
|
9
|
+
# * Redistributions of source code must retain the above copyright notice,
|
10
|
+
# this list of conditions and the following disclaimer.
|
11
|
+
#
|
12
|
+
# * Redistributions in binary form must reproduce the above copyright
|
13
|
+
# notice, this list of conditions and the following disclaimer in the
|
14
|
+
# documentation and/or other materials provided with the distribution.
|
15
|
+
#
|
16
|
+
# * The names of its contributors may not be used to endorse or promote
|
17
|
+
# products derived from this software without specific prior written
|
18
|
+
# permission.
|
19
|
+
#
|
20
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
21
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
22
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
23
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
24
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
25
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
26
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
27
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
28
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
29
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
30
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
31
|
+
# =============================================================================
|
32
|
+
#++
|
33
|
+
|
34
|
+
$:.unshift "../lib"
|
35
|
+
|
36
|
+
require 'test/unit'
|
37
|
+
require 'copland/thread'
|
38
|
+
|
39
|
+
class TC_QueryableMutex < Test::Unit::TestCase
|
40
|
+
|
41
|
+
def test_lock
|
42
|
+
mutex = Copland::QueryableMutex.new
|
43
|
+
assert !mutex.self_locked?
|
44
|
+
mutex.lock
|
45
|
+
assert mutex.self_locked?
|
46
|
+
mutex.unlock
|
47
|
+
assert !mutex.self_locked?
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_reacquire_error
|
51
|
+
mutex = Copland::QueryableMutex.new
|
52
|
+
mutex.lock
|
53
|
+
assert_raise( ThreadError ) do
|
54
|
+
mutex.lock
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_safe_reacquire
|
59
|
+
mutex = Copland::QueryableMutex.new
|
60
|
+
mutex.lock
|
61
|
+
|
62
|
+
t = Thread.new do
|
63
|
+
assert mutex.locked?
|
64
|
+
assert !mutex.self_locked?
|
65
|
+
mutex.synchronize do
|
66
|
+
assert mutex.self_locked?
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
assert_nil t.join(0.1)
|
71
|
+
mutex.unlock
|
72
|
+
assert_not_nil t.join
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|