Skip to content

Instantly share code, notes, and snippets.

@araraloren
Last active January 27, 2019 05:33
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save araraloren/cfb7d7b694be76e0bbe53491df573d3a to your computer and use it in GitHub Desktop.

Revisions

  1. araraloren revised this gist Jan 27, 2019. 2 changed files with 19 additions and 11 deletions.
    28 changes: 18 additions & 10 deletions lib-Song-Pluggable.pm6
    @@ -1,5 +1,7 @@
    unit class Song::Pluggable is export;

    state $threadlock = Lock::Async.new;

    has $.file;
    has $!lock;
    has @!plugins;
    @@ -24,11 +26,15 @@ method plugins() {
    }

    method lock() {
    $!lock.lock(); self;
    $threadlock.protect: {
    $!lock.lock();
    }
    }

    method unlock() {
    $!lock.unlock(); self;
    $threadlock.protect: {
    $!lock.unlock();
    }
    }

    method find(Str $name) {
    @@ -56,14 +62,16 @@ method !append-plugin-to-config(Str $name, Bool $enable) {
    }

    method !make-plugin-info(Str $name, Bool $enable) {
    Info.new(
    enable => $enable,
    plugin => do {
    ((try require ::($name)) === Nil) ?? Any !! ::($name)
    },
    name => $name,
    installed => !((try require ::($name)) === Nil),
    )
    $threadlock.protect: {
    Info.new(
    enable => $enable,
    plugin => do {
    ((try require ::($name)) === Nil) ?? Any !! ::($name)
    },
    name => $name,
    installed => !((try require ::($name)) === Nil),
    )
    }
    }

    class Info {
    2 changes: 1 addition & 1 deletion test.p6
    @@ -2,7 +2,7 @@ use Song::Pluggable;

    my @threads;

    for ^2 {
    for ^5 {
    @threads.push(
    start {
    given Song::Pluggable.new(file => "plugin.json") {
  2. araraloren created this gist Jan 26, 2019.
    1 change: 1 addition & 0 deletions lib-Song-Command-List.pm6
    @@ -0,0 +1 @@
    unit module Song::Command::List;
    78 changes: 78 additions & 0 deletions lib-Song-Pluggable.pm6
    @@ -0,0 +1,78 @@
    unit class Song::Pluggable is export;

    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() {
    $!lock.lock(); self;
    }

    method unlock() {
    $!lock.unlock(); self;
    }

    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) {
    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(|%_);
    }
    }
    20 changes: 20 additions & 0 deletions plugin.json
    @@ -0,0 +1,20 @@
    {
    "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
    }
    ]
    }
    27 changes: 27 additions & 0 deletions test.p6
    @@ -0,0 +1,27 @@
    use Song::Pluggable;

    my @threads;

    for ^2 {
    @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;