Last active
January 27, 2019 05:33
-
-
Save araraloren/cfb7d7b694be76e0bbe53491df573d3a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
unit module Song::Command::List; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
unit class Song::Pluggable is export; | |
state $threadlock = Lock::Async.new; | |
has $.file; | |
has $!lock; | |
has @!plugins; | |
submethod TWEAK() { | |
$!lock = $!file.IO.dirname.IO.add(".lock").open(:create, :rw); | |
} | |
class Info { ... } | |
method load() { | |
my %config = Rakudo::Internals::JSON.from-json(slurp($!file)); | |
@!plugins = []; | |
for @(%config<plugins>) -> $plugin { | |
@!plugins.push(self!make-plugin-info($plugin<name>.Str, $plugin<enable>.Bool)); | |
} | |
self; | |
} | |
method plugins() { | |
@!plugins; | |
} | |
method lock() { | |
$threadlock.protect: { | |
$!lock.lock(); | |
} | |
} | |
method unlock() { | |
$threadlock.protect: { | |
$!lock.unlock(); | |
} | |
} | |
method find(Str $name) { | |
@!plugins.grep(*.name eq $name); | |
} | |
method exists(Str $name) { | |
@!plugins.grep(*.name eq $name).elems > 0; | |
} | |
method register(Str $name, Bool $enable) { | |
if self.exists($name) { | |
die "The plugin is already existed: $name"; | |
} | |
else { | |
@!plugins.push($name, $enable); | |
self!append-plugin-to-config($name, $enable); | |
} | |
} | |
method !append-plugin-to-config(Str $name, Bool $enable) { | |
my %config = Rakudo::Internals::JSON.from-json(slurp($!file)); | |
%config<plugins>.push(%{ name => $name, enable => $enable }); | |
spurt($!file, Rakudo::Internals::JSON.to-json(%config)); | |
} | |
method !make-plugin-info(Str $name, Bool $enable) { | |
$threadlock.protect: { | |
Info.new( | |
enable => $enable, | |
plugin => do { | |
((try require ::($name)) === Nil) ?? Any !! ::($name) | |
}, | |
name => $name, | |
installed => !((try require ::($name)) === Nil), | |
) | |
} | |
} | |
class Info { | |
has $.enable; | |
has $.plugin; | |
has $.installed; | |
has $.name; | |
method get-instance(*%_) { | |
$!plugin.new(|%_); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"plugins" : [ | |
{ | |
"name" : "Song::Command::Install", | |
"enable" : true | |
}, | |
{ | |
"name" : "Song::Command::Remove", | |
"enable" : true | |
}, | |
{ | |
"name" : "Song::Command::List", | |
"enable" : true | |
}, | |
{ | |
"name" : "Song::Command::Update", | |
"enable" : true | |
} | |
] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use Song::Pluggable; | |
my @threads; | |
for ^5 { | |
@threads.push( | |
start { | |
given Song::Pluggable.new(file => "plugin.json") { | |
say "IN THREAD {$*THREAD.id}: ", .gist, .WHICH; | |
.lock(); | |
.load(); | |
.unlock(); | |
say "IN THREAD {$*THREAD.id}: ", .gist for .plugins(); | |
.lock(); | |
try .register('Song::Command::Update', True); | |
.unlock(); | |
say "IN THREAD {$*THREAD.id} LOAD AGAIN"; | |
.lock(); | |
.load(); | |
.unlock(); | |
say "AGAIN, IN THREAD {$*THREAD.id}: ", .gist for .plugins(); | |
} | |
} | |
) | |
} | |
await @threads; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
It is recommended to use
Lock.protect
instead ofLock.lock
andLock.unlock
For one, if there is an error in one of those calls the corresponding
unlock
might not get called.Also if
Song::Pluggable.load
needs to be locked, why doesn't it do the locking itself?If every method needs to be locked, use OO::Monitors, and it will do all the locking for you.