GithubHelp home page GithubHelp logo

vegardit / haxe-concurrent Goto Github PK

View Code? Open in Web Editor NEW
82.0 8.0 14.0 526 KB

A haxelib for basic platform-agnostic concurrency support

Home Page: https://vegardit.github.io/haxe-concurrent/

License: Apache License 2.0

Haxe 92.16% Batchfile 7.28% HTML 0.14% JavaScript 0.42%
haxe haxelib concurrency scheduler thread thread-pool executor lock hashlink neko

haxe-concurrent's Introduction

haxe-concurrent - cross-platform concurrency support

Build Status Release License Contributor Covenant

  1. What is it?
  2. hx.concurrent.atomic package
  3. hx.concurrent.collection package
  4. hx.concurrent.executor package
  5. hx.concurrent.event package
  6. hx.concurrent.lock package
  7. hx.concurrent.thread package
  8. Installation
  9. Using the latest code
  10. License
  11. Alternatives

What is it?

A haxelib that provides some basic platform agnostic concurrency support.

All classes are located in the package hx.concurrent or below.

The library has been extensively unit tested (over 400 individual test cases) on the targets C++, C#, Eval, Flash, HashLink, Java, JavaScript (Node.js and PhantomJS), Lua, Neko, PHP 7 and Python 3.

Note:

  • When targeting Flash the option -swf-version 11.5 (or higher) must be specified, otherwise you will get Class flash.concurrent::Condition could not be found.
  • When targeting C# the option -D net-ver=45 must be specified, otherwise you may get error CS0234: The type or namespace name 'Volatile' does not exist in the namespace 'System.Threading'. Are you missing an assembly reference?
  • Multi-threading/locking support in Eval is broken, see some of the unresolved issues:

Haxe compatibility

haxe-concurrent Haxe
1.0.0 to 1.2.0 3.2.1 or higher
2.0.0 to 2.1.3 3.4.2 or higher
3.0.0 or higher 4.0.5 or higher
4.0.0 or higher 4.2.0 or higher

The hx.concurrent.atomic package

The hx.concurrent.atomic package contains mutable value holder classes that allow for thread.safe manipulation:

The hx.concurrent.collection package

The hx.concurrent.collection package contains thread-safe implementations of different types of collections:

The hx.concurrent.executor package

The hx.concurrent.executor package contains Executor implementations that allow to execute functions concurrently and to schedule tasks for later/repeated execution.

On platform with the thread support (C++, C#, Eval, HashLink, Neko, Python, Java) threads are used to realize true concurrent execution, on other platforms haxe.Timer is used to at least realize async execution.

import hx.concurrent.executor.Schedule;
import hx.concurrent.executor.Executor;

class Test {

   static function main() {
      var executor = Executor.create(3);  // <- 3 means to use a thread pool of 3 threads on platforms that support threads
      // depending on the platform either a thread-based or timer-based implementation is returned

      // define a function to be executed concurrently/async/scheduled (return type can also be Void)
      var myTask = function():Date {
         trace("Executing...");
         return Date.now();
      }

      // submit 10 tasks each to be executed once asynchronously/concurrently as soon as possible
      for (i in 0...10) {
         executor.submit(myTask);
      }

      executor.submit(myTask, ONCE(2000));            // async one-time execution with a delay of 2 seconds
      executor.submit(myTask, FIXED_RATE(200));       // repeated async execution every 200ms
      executor.submit(myTask, FIXED_DELAY(200));      // repeated async execution 200ms after the last execution
      executor.submit(myTask, HOURLY(30));            // async execution 30min after each full hour
      executor.submit(myTask, DAILY(3, 30));          // async execution daily at 3:30
      executor.submit(myTask, WEEKLY(SUNDAY, 3, 30)); // async execution Sundays at 3:30

      // submit a task and keep a reference to it
      var future = executor.submit(myTask, FIXED_RATE(200));

      // check if a result is already available
      switch (future.result) {
         case VALUE(value, time, _): trace('Successfully execution at ${Date.fromTime(time)} with result: $value');
         case FAILURE(ex, time, _):  trace('Execution failed at ${Date.fromTime(time)} with exception: $ex');
         case PENDING(_):            trace("No result yet...");
      }

      // check if the task is scheduled to be executed (again) in the future
      if (!future.isStopped) {
         trace('The task is scheduled for further executions with schedule: ${future.schedule}');
      }

      // cancel any future execution of the task
      future.cancel();
   }
}

The hx.concurrent.event package

The hx.current.event package contains classes for type-safe event dispatching.

import hx.concurrent.event.AsyncEventDispatcher;
import hx.concurrent.event.SyncEventDispatcher;
import hx.concurrent.Future;
import hx.concurrent.executor.Executor;

class Test {

   static function main() {
      /**
       * create a dispatcher that notifies listeners/callbacks synchronously in the current thread
       */
      var syncDispatcher = new SyncEventDispatcher<String>(); // events are of type string

      // create event listener
      var onEvent = function(event:String):Void {
         trace('Received event: $event');
      }

      syncDispatcher.subscribe(onEvent);

      // notify all registered listeners synchronously,
      // meaning this method call blocks until all listeners are finished executing
      syncDispatcher.fire("Hey there");

      /**
       * create a dispatcher that notifies listeners asynchronously using an executor
       */
      var executor = Executor.create(5); // thread-pool with 5 threads
      var asyncDispatcher = new AsyncEventDispatcher<String>(executor);

      // create event listener
      var onAsyncEvent = function(event:String):Void {
         trace('Received event: $event');
      }

      // notify all registered listeners asynchronously,
      // meaning this method call returns immediately
      asyncDispatcher.fire("Hey there");

      // fire another event and get notified when all listeners where notified
      var future = asyncDispatcher.fire("Boom");

      asyncDispatcher.subscribe(onAsyncEvent);

      future.onCompletion(result -> {
         switch(result) {
            case VALUE(count, _): trace('$count listeners were successfully notified');
            case FAILURE(ex, _):  trace('Event could not be delivered because of: $ex');
            case PENDING(_):      trace("Nothing is happening");
          }
      });
   }
}

The hx.concurrent.lock package

The hx.concurrent.lock package contains lock implementations for different purposes:

The hx.concurrent.thread package

The hx.concurrent.thread package contains classes for platforms supporting threads:

  • ThreadPool - basic thread-pool implementation supporting C++, C#, HashLink, Neko, Java and Python. For advanced concurrency or cross-platform requirements use Executor instead.

    import hx.concurrent.thread.*;
    
    class Test {
    
       static function main() {
          var pool = new ThreadPool(4); // 4 concurrent threads
    
          pool.submit(function(ctx:ThreadContext) {
             // do some work here
          });
    
          pool.awaitCompletion(30 * 1000); // wait 30 seconds for all submitted tasks to be processed
    
          pool.cancelPendingTasks(); // cancels execution of all currently queued tasks
    
          // initiate graceful stop of all running threads, i.e. they finish the current tasks they process
          // execution of all other queued tasks is cancelled
          pool.stop();
       }
    }
  • Threads

Installation

  1. install the library via haxelib using the command:

    haxelib install haxe-concurrent
    
  2. use in your Haxe project

    • for OpenFL/Lime projects add <haxelib name="haxe-concurrent" /> to your project.xml
    • for free-style projects add -lib haxe-concurrent to your *.hxml file or as command line option when running the Haxe compiler

Using the latest code

Using haxelib git

haxelib git haxe-concurrent https://github.com/vegardit/haxe-concurrent main D:\haxe-projects\haxe-concurrent

Using Git

  1. check-out the main branch

    git clone https://github.com/vegardit/haxe-concurrent --branch main --single-branch D:\haxe-projects\haxe-concurrent
    
  2. register the development release with Haxe

    haxelib dev haxe-concurrent D:\haxe-projects\haxe-concurrent
    

License

All files are released under the Apache License 2.0.

Individual files contain the following tag instead of the full license text:

SPDX-License-Identifier: Apache-2.0

This enables machine processing of license information based on the SPDX License Identifiers that are available here: https://spdx.org/licenses/.

Alternatives

Other libraries addressing concurrency/parallelism:

haxe-concurrent's People

Contributors

aidan63 avatar dependabot[bot] avatar dpomier avatar onehundredfeet avatar paq avatar sebthom avatar syedasimalise avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

haxe-concurrent's Issues

logs on startup

haxe-concurrent prints some logs when it starts up (e.g. hx/concurrent/Service.hx:56: [hx.concurrent.executor.TimerExecutor#1] instantiated). Since I include haxe-concurrent in a library of mine, which I then give to customers, they get worried when they see some unexpected messages on the console.
Is it possible to avoid these logs?

"Virtual functions are pure" build error with RLock (HXCPP)

The following error occurs during compilation of any project which includes hx.concurrent.lock.RLock, even a minimal one.,

Error: ./src/hx/concurrent/lock/RLock.cpp: In static member function ‘static Dynamic hx::concurrent::lock::RLock_obj::__CreateEmpty()’:
./src/hx/concurrent/lock/RLock.cpp:47:49: error: invalid new-expression of abstract class type ‘hx::concurrent::lock::RLock_obj’
   47 | Dynamic RLock_obj::__CreateEmpty() { return new RLock_obj; }
      |                                                 ^~~~~~~~~
In file included from ./src/hx/concurrent/lock/RLock.cpp:13:
include/hx/concurrent/lock/RLock.h:21:30: note:   because the following virtual functions are pure within ‘hx::concurrent::lock::RLock_obj’:
   21 | class HXCPP_CLASS_ATTRIBUTES RLock_obj : public  ::hx::concurrent::lock::AbstractAcquirable_obj
      |                              ^~~~~~~~~
In file included from ./src/hx/concurrent/lock/RLock.cpp:7:
include/hx/concurrent/lock/AbstractAcquirable.h:48:30: note:     ‘virtual bool hx::concurrent::lock::AbstractAcquirable_obj::tryAcquire(int)’
   48 |                 virtual bool tryAcquire(int timeoutMS) = 0;
      |                              ^~~~~~~~~~
./src/hx/concurrent/lock/RLock.cpp: In static member function ‘static Dynamic hx::concurrent::lock::RLock_obj::__Create(hx::DynamicArray)’:
./src/hx/concurrent/lock/RLock.cpp:53:65: error: invalid new-expression of abstract class type ‘hx::concurrent::lock::RLock_obj’
   53 |         ::hx::ObjectPtr< RLock_obj > _hx_result = new RLock_obj();
      |                                                                 ^
./src/hx/concurrent/lock/RLock.cpp: In static member function ‘static hx::ObjectPtr<hx::concurrent::lock::RLock_obj> hx::concurrent::lock::RLock_obj::__new()’:
./src/hx/concurrent/lock/RLock.cpp:211:61: error: invalid new-expression of abstract class type ‘hx::concurrent::lock::RLock_obj’
  211 |         ::hx::ObjectPtr< RLock_obj > __this = new RLock_obj();
      |                                                             ^
./src/hx/concurrent/lock/RLock.cpp: In static member function ‘static void hx::concurrent::lock::RLock_obj::__register()’:
./src/hx/concurrent/lock/RLock.cpp:356:19: error: cannot declare variable ‘_hx_dummy’ to be of abstract type ‘hx::concurrent::lock::RLock_obj’
  356 |         RLock_obj _hx_dummy;
      |                   ^~~~~~~~~

Building with HXCPP on the Linux platform.

Python 3.7 support

Python 3.7 has marked await and async as reserved words. Threads.await (and latch) will no longer run on systems using that. await needs to be renamed either for all platforms or just python to work properly.

Created a fork with "a" fix but might not be the best.
https://github.com/azupko/haxe-concurrent

Error with latest Heapsio(hashlink target) and Haxe 4.0.0-rc2

There are just one statement in main:
Executor.create(1);

Lock was aquired by another thread!
Called from hx.concurrent.lock.RLock.release (hx/concurrent/lock/RLock.hx line 201)
Called from hx.concurrent.atomic._AtomicInt.AtomicIntImpl.incrementAndGet (hx/concurrent/atomic/AtomicInt.hx line 158)
Called from hx.concurrent.$ServiceBase.__constructor__ (hx/concurrent/Service.hx line 56)
Called from hx.concurrent.executor.$Executor.__constructor__ (hx/concurrent/executor/Executor.hx line 19)
Called from hx.concurrent.executor.$ThreadPoolExecutor.__constructor__ (hx/concurrent/executor/ThreadPoolExecutor.hx line 40)
Called from hx.concurrent.executor.$Executor.create (hx/concurrent/executor/Executor.hx line 31)
Called from com.test.$ClientHeaps.main (com/test/ClientHeaps.hx line 28)

How to ensure event is fired only Once!

I am using the hx.concurrent.event package to implement a wrapper for an EventEmitter based on the Javascript EventEmitter API.

This is my implementation

class EventEmitter {
	final signals:Map<String, SyncEventDispatcher<haxe.Rest<Any>>>;
    final one_signals:Map<String, SyncEventDispatcher<haxe.Rest<Any>>>;
    final one_listeners:Map<String, Array<(...v:Any) -> Void>>;
    // static final executor:Executor = Executor.create(2);
	public function new() {
		signals = new Map();
        one_signals = new Map();
        one_listeners = new Map();
	}
    public function setMaxListeners(count:Int) {
		// maxListeners = count;
	}
	public function on(name:String, callback:(...v:Any) -> Void) {
		var asyncDispatcher = new SyncEventDispatcher<haxe.Rest<Any>>();
		if (signals.exists(name)) {
			signals.get(name).subscribe(callback);
		} else {
            asyncDispatcher.subscribe(callback);
			signals.set(name, asyncDispatcher);
		}
	}
	public function once(name:String, callback:(...v:Any) -> Void) {
		var asyncDispatcher = new SyncEventDispatcher<haxe.Rest<Any>>();
		asyncDispatcher.subscribe(callback);
		if (one_signals.exists(name)) {
            var s = one_signals.get(name);
			s.subscribe(callback);
		} else {
            asyncDispatcher.subscribe(callback);
			one_signals.set(name, asyncDispatcher);
		}
        if(one_listeners.exists(name)){
            var l = one_listeners.get(name);
            l.push(callback);
        } else {
            one_listeners.set(name, [callback]);
        }
	}
	public function emit(name:String, ...v:Any) {
		if (signals.exists(name)) {
			final signal = signals.get(name);
            signal.fire(...v);
		}
        if(one_signals.exists(name)){
            final one_signal = one_signals.get(name);
            var s = one_signal.fire(...v);
            s.onResult = (result:FutureResult<Int>)->{
                switch result {
                    case SUCCESS(result, time, future):{
                        one_signal.unsubscribe(one_listeners[name][result-1]);
                        one_signals.remove(name);
                    }
                    case FAILURE(ex, _): trace('Event could not be delivered because of: $ex');
                    case _:
                }
            };
        }
	}
}

when I use eventEmitter.once function, an older listener still fires in another call. How do I ensure that a listener can only be fired one?

[jvm] ExceptionInInitializerError

When I run my tests with haxe-concurrent 5.1.3 and haxe 4.3.1, I get the following error. However if I compile the same tests with haxe 4.3-rc.1, they work fine.
Unfortunately I am not able to reproduce the error by means of a simple test, but the basic execution flow is trivial: I create an instance of Executor in a static variable and, when I try to call the method submit on it from the method Test.delay, the exception ExceptionInInitializerError is thrown.

java.lang.ExceptionInInitializerError
          at utest.Test.delay(test-util/utest/Test.hx:152)
          at utest.Runner.runCurrent(test-util/utest/Runner.hx:129)
          at utest.Runner.gotoFirstTest(test-util/utest/Runner.hx:85)
          at utest.Runner$Closure_evtRun_0.invoke(test-util/utest/Runner.hx:60)
          at utest.Runner$Closure_evtRun_0.invoke(test-util/utest/Runner.hx)
          at hx.concurrent.lock.AbstractAcquirable.execute(/Users/acarioni/haxe/haxe_libraries/haxe-concurrent/5.1.3/haxelib/src/hx/concurrent/lock/Acquirable.hx:55)
          at utest.Runner.evtRun(test-util/utest/Runner.hx:55)
          at utest.Runner$Closure_run_0.invoke(test-util/utest/Runner.hx:52)
          at utest.Runner$Closure_run_0.invoke(test-util/utest/Runner.hx)
          at hx.concurrent.lock.AbstractAcquirable.execute(/Users/acarioni/haxe/haxe_libraries/haxe-concurrent/5.1.3/haxelib/src/hx/concurrent/lock/Acquirable.hx:55)
          at utest.Runner.run(test-util/utest/Runner.hx:50)
          at haxe.root.TestAll.main(test/TestAll.hx:93)
          at haxe.root.TestAll.main(test/TestAll.hx:1)
      Caused by: java.lang.ClassCastException: class hx.concurrent.thread.ThreadPool$Closure_onStart_0 cannot be cast to class java.lang.Runnable (hx.concurrent.thread.ThreadPool$Closure_onStart_0 is in unnamed module of loader 'app'; java.lang.Runnable is in module java.base of loader 'bootstrap')
          at sys.thread.Thread$NativeHaxeThread.<init>(/Users/acarioni/haxe/versions/4.3.1/std/java/_std/sys/thread/Thread.hx:160)
          at sys.thread.Thread$HaxeThread.create(/Users/acarioni/haxe/versions/4.3.1/std/java/_std/sys/thread/Thread.hx:104)
          at hx.concurrent.thread.ThreadPool.onStart(/Users/acarioni/haxe/haxe_libraries/haxe-concurrent/5.1.3/haxelib/src/hx/concurrent/thread/ThreadPool.hx:102)
          at hx.concurrent.ServiceBase$Closure_start_0.invoke(/Users/acarioni/haxe/haxe_libraries/haxe-concurrent/5.1.3/haxelib/src/hx/concurrent/Service.hx:65)
          at hx.concurrent.ServiceBase$Closure_start_0.invoke(/Users/acarioni/haxe/haxe_libraries/haxe-concurrent/5.1.3/haxelib/src/hx/concurrent/Service.hx)
          at hx.concurrent.lock.AbstractAcquirable.execute(/Users/acarioni/haxe/haxe_libraries/haxe-concurrent/5.1.3/haxelib/src/hx/concurrent/lock/Acquirable.hx:55)
          at hx.concurrent.ServiceBase.start(/Users/acarioni/haxe/haxe_libraries/haxe-concurrent/5.1.3/haxelib/src/hx/concurrent/Service.hx:58)
          at hx.concurrent.thread.ThreadPool.<init>(/Users/acarioni/haxe/haxe_libraries/haxe-concurrent/5.1.3/haxelib/src/hx/concurrent/thread/ThreadPool.hx:61)
          at hx.concurrent.executor.ThreadPoolExecutor.<init>(/Users/acarioni/haxe/haxe_libraries/haxe-concurrent/5.1.3/haxelib/src/hx/concurrent/executor/ThreadPoolExecutor.hx:41)
          at hx.concurrent.executor.Executor.create(/Users/acarioni/haxe/haxe_libraries/haxe-concurrent/5.1.3/haxelib/src/hx/concurrent/executor/Executor.hx:36)
          at utest.Test$Test_Fields_.<clinit>(test-util/utest/Test.hx:10)
          ... 13 more

Unsupported recursive type when importing hx.concurrent.executor.Executor

When building a haxe project that include the concurrent library against the HashLink target, I get the following error:

/haxe/lib/haxe-concurrent/5,1,3/src/hx/concurrent/Future.hx:13: characters 1-64 : Unsupported recursive type

Steps to reproduce:

Haxe-concurrent 5.1.3
Haxe 4.3.4
OS: Macosx Monterey 12.7.3

program "Main.hx"

package;

import hx.concurrent.executor.Executor;

class Main {
   public static function main() {
      var executor = Executor.create(3);
      executor.submit(()->{trace("hello.");});
   }
}

build .hxml:

-cp src
-lib haxe-concurrent
-main Main
--hl bin/main.hl

My expectation is that this is a bug with Haxe itself, however I am not familiar enough with either the library or the HashLink target to know for sure.

Concurrent Map

Hi, just found this library and it seems great. Was just wondering if there are plans to implement a Concurrent Map?

Hashlink CG thread issue

When working with the ThreadPool on Hashlink the error below gets raised. This happens after the submitted tasks are executed.

src/gc.c(232) : FATAL ERROR : Can't lock GC in unregistered thread

OS: MacOS Catalina
Haxe version: 4.2.1+bf9ff69
Hashlink version: 1.12.0 (Github master)

Any ideas? Thanks in advance!

Right way to set the threads flag

I've incorporated this haxelib into a project that I'm working on which is currently targeting Java, and I was wondering how you were intending on the threads flag to be set: whether the haxelib has some magic that handles this on its own, or if I should be manually adding the -D threads argument in my build file (or using the hx.concurrent.internal.Macros.addDefines() macro).

Basically, is the intention that I add the flag myself to builds that I know can handle threads, or is this something that should be handled by the haxelib - and if the latter, what's the right way to trigger this? I'm setting it manually right now and it seems to be working well.

Example ?

Hi,

I'm trying to use the executor but I can't find a way to wait for execution to complete, all the examples from the readme are not contained so I can't reproduce any.
Do you have a simple working example besides the test file?

Thanks

Investigating Possible Memory Leak with Executor

Hello,
Appologies if the issue ends up not being in your library, I'm trying to debug a memory leak in a larger program and have managed to reproduce it in a small sample, just thought I'd run it past you first.

import haxe.io.Bytes;
import hx.concurrent.executor.Executor;

function main()
{
	final executor = Executor.create(4);
	final futures  = genFutures(executor);

	while (true)
	{
		switch Sys.stdin().readLine()
		{
			case 'exit':
				return;
			case 'free':
				for (future in futures)
				{
					future.cancel();
				}

				futures.resize(0);

				trace(cpp.vm.Gc.memUsage());

				cpp.vm.Gc.run(true);

				trace(cpp.vm.Gc.memUsage());
			case _:
				//
		}
	}
}

function genFutures(_executor : Executor)
{
	return [
		for (_ in 0...10)
		{
			final bytes = Bytes.alloc(4096 * 4096 * 4);

			_executor.submit(() -> {
				trace('captured a bytes object with ${ bytes.length } bytes');
			});
		}
	];
}

With the above program the 10 bytes objects are never collected by the GC, I've had a quick look through the threaded executor and thread pool class and it doesn't seem like they hold references to the futures after they've been ran so I'm not sure as to why the bytes objects are not collected.

My understanding is that the closure passed to the submit function will capture the bytes object, and since nothing else has a reference to it (and they won't be on the stack after the function returns) they should be eligiable for collection after the future is completed.

While the debug info and forced GC running is hxcpp specific I get the same behaviour on hashlink. I was kind of hoping writing this all out would help me understand the issue a bit more but I'm still not sure, I could just be mis-understanding how GCs work with closures. In any case it would be good to get a confirmation that the executor shouldn't be holding a reference to anything in this case.

Cheers!

Package naming issue.

Hi,

there is a problem with package naming,

In source code it is

package hx.concurrent;
import hx.concurrent.lock.RLock;

and in physical folder it is:

src/hx/concurrent

because of this none of the IDE's are able to recognize classes.

Intellij will add the imports but can't recognize the classes. [cpp]
Flash Develop can't read the lib. [OpenFl]

what i did to solve :

just moved the hx pacakge out of src folder at library path.

hx/concurrent

now the Intellij is able to recognize everything but in Flash Develop i had to add
the lib to the Global Class paths.

thanks.

CPP abstract class error when building with Lime

This issue is similar to that of #21, however after revisiting the issue recently and finding that the Travix tests function properly, I decided to perform a more thorough investigation.

As a result, I discovered the issue and have developed a minimal reproduction and provided additional logs.

The core issue is, I believe, with the lime framework, whose purpose is to provide additional utilities for cross-platform development, such as common interfaces for functionality like rendering. This library supercedes the build tools provided by Haxe, and some of the command line arguments it adds may be causing these build problems.

I was able to reproduce my problems with the following steps:

  1. Install Lime via Haxelib (haxelib install lime)
  2. Create a minimal Lime sample project (lime create HelloWorld)
  3. Open project.xml and add the haxelib (<haxelib name="haxe-concurrent" />)
  4. Add code to Main.hx to use the library (I simply added code which instantiates a RLock and nothing else)
  5. Attempt to build the project (lime build windows)

The build fails with an error relating to methods of an abstract class. I am not an expert in C++ compilation but my theory is that the issue arises from one of the build flags enforced by Lime.

I have uploaded the project where I reproduced the issue to GitHub Below are the full logs from the build process:

Executing task: lime build windows --connect 6001 

C:/HaxeToolkit/Haxe425/haxe/lib/haxe-concurrent/4,0,0/src/hx/concurrent/internal/Macros.hx:35: [INFO] Setting compiler define 'threads'.
Creating D:/Programming/Haxe/Lime-HelloWorld/Export/windows/obj/obj/msvc1964-nc/__pch/haxe/hxcpp.pch...
hxcpp.cpp

Compiling group: haxe
cl.exe -Iinclude -nologo /WX- /fp:precise -DHX_WINDOWS -GR -O2(optim-std) -Zi(debug) -FdD:\Programming\Haxe\Lime-HelloWorld\Export\windows\obj\obj/msvc1964-nc/vc.pdb(debug) -Od(debug) -O2(release) -Os(optim-size) -FS -Oy- -c -EHs -GS- -IC:/HaxeToolkit/Haxe425/haxe/lib/hxcpp/4,2,1/include -DHXCPP_M64 -DHXCPP_VISIT_ALLOCS(haxe) -DHX_SMART_STRINGS(haxe) -DHXCPP_API_LEVEL=400(haxe) -D_CRT_SECURE_NO_DEPRECATE -D_ALLOW_MSC_VER_MISMATCH -D_ALLOW_ITERATOR_DEBUG_LEVEL_MISMATCH -DHX_WIN_MAIN(main) -wd4996 ... tags=[haxe,static]
 - src/lime/app/_Event_lime_ui_Window_Void.cpp  [haxe,release]
 - src/lime/media/openal/_ALAuxiliaryEffectSlot/ALAuxiliaryEffectSlot_Impl_.cpp
 - src/lime/system/SensorType.cpp
 - src/sys/io/_Process/Stdout.cpp
 - src/lime/_internal/backend/native/TextEventInfo.cpp
 - src/lime/graphics/cairo/_CairoFontOptions/CairoFontOptions_Impl_.cpp
 - src/lime/math/Rectangle.cpp  [haxe,release]
 - src/sys/FileSystem.cpp 
 - src/lime/graphics/opengl/ext/EXT_multi_draw_arrays.cpp 
 - src/lime/utils/_Int32Array/Int32Array_Impl_.cpp 
 - src/lime/media/openal/ALC.cpp  [haxe,release]
 - src/haxe/ValueException.cpp 
 - src/lime/media/openal/_ALContext/ALContext_Impl_.cpp
 - src/lime/graphics/opengl/ext/EXT_debug_marker.cpp
 - src/lime/system/_ThreadPool/ThreadPoolMessage.cpp
 - src/lime/app/_Future/FutureWork.cpp  [haxe,release]
 - src/lime/_internal/backend/native/WindowEventInfo.cpp 
 - src/lime/graphics/opengl/ext/OES_vertex_half_float.cpp
 - src/haxe/StackItem.cpp
 - src/lime/app/Promise.cpp  [haxe,release]
 - src/lime/_internal/backend/native/MouseEventInfo.cpp 
 - src/lime/graphics/opengl/ext/NV_fence.cpp 
 - src/lime/_internal/macros/AssetsMacro.cpp
 - src/lime/graphics/opengl/ext/EXT_texture_format_BGRA8888.cpp 
 - src/haxe/crypto/BaseCode.cpp 
 - src/lime/graphics/opengl/ext/OES_surfaceless_context.cpp 
 - src/lime/_internal/format/LZMA.cpp  [haxe,release]
 - src/lime/graphics/opengl/ext/APPLE_texture_format_BGRA8888.cpp 
 - src/lime/graphics/cairo/_CairoFontFace/CairoFontFace_Impl_.cpp 
 - src/lime/graphics/opengl/ext/QCOM_binning_control.cpp 
 - src/lime/graphics/opengl/_GLBuffer/GLBuffer_Impl_.cpp 
 - src/lime/app/_Event_lime_graphics_RenderContext_Void.cpp  [haxe,release]
 - src/lime/graphics/opengl/ext/OES_depth_texture.cpp 
 - src/lime/graphics/opengl/ext/OES_standard_derivatives.cpp 
 - src/__boot__.cpp 
 - src/lime/ui/_GamepadAxis/GamepadAxis_Impl_.cpp
 - src/lime/system/_ThreadPool/ThreadPoolMessageType.cpp 
 - src/lime/graphics/opengl/ext/EXT_color_buffer_float.cpp 
 - src/lime/graphics/opengl/ext/DMP_shader_binary.cpp 
 - src/Std.cpp 
 - src/sys/thread/_Thread/HaxeThread.cpp 
 - src/lime/net/curl/CURLMultiMessage.cpp 
 - src/lime/graphics/opengl/ext/EXT_shader_texture_lod.cpp 
 - src/lime/graphics/Image.cpp  [haxe,release]
 - src/lime/utils/Preloader.cpp  [haxe,release]
 - src/lime/graphics/_OpenGLES3RenderContext/OpenGLES3RenderContext_Impl_.cpp 
 - src/lime/media/WebAudioContext.cpp 
 - src/lime/graphics/opengl/ext/APPLE_texture_max_level.cpp 
 - src/lime/graphics/_WebGL2RenderContext/WebGL2RenderContext_Impl_.cpp 
 - src/haxe/NativeStackTrace.cpp 
 - src/sys/thread/_EventLoop/RegularEvent.cpp 
 - src/lime/utils/AssetManifest.cpp  [haxe,release]
 - src/lime/text/GlyphMetrics.cpp  [haxe,release]
 - src/ValueType.cpp 
 - src/lime/media/FlashAudioContext.cpp 
 - src/lime/math/_BGRA/BGRA_Impl_.cpp 
 - src/lime/graphics/opengl/ext/QCOM_writeonly_rendering.cpp 
 - src/lime/_internal/backend/native/NativeCFFI.cpp  [haxe,release]
 - src/lime/math/Vector4.cpp  [haxe,release]
 - src/lime/graphics/opengl/ext/OES_mapbuffer.cpp 
 - src/lime/_internal/graphics/StackBlur.cpp 
 - src/haxe/Exception.cpp 
 - src/lime/graphics/opengl/ext/VIV_shader_binary.cpp 
 - src/lime/_internal/format/BMP.cpp  [haxe,release]
 - src/lime/_internal/backend/native/RenderEventInfo.cpp 
 - src/haxe/io/Input.cpp 
 - src/lime/system/JNIStaticField.cpp  [haxe,release]
 - src/lime/graphics/opengl/ext/OES_compressed_ETC1_RGB8_texture.cpp 
 - src/lime/system/_CFFIPointer/CFFIPointer_Impl_.cpp 
 - src/lime/media/vorbis/VorbisFile.cpp 
 - src/lime/media/openal/AL.cpp  [haxe,release]
 - src/lime/graphics/opengl/ext/OES_depth32.cpp 
 - src/lime/media/openal/_ALEffect/ALEffect_Impl_.cpp 
 - src/lime/graphics/opengl/ext/OES_texture_half_float_linear.cpp 
 - src/lime/graphics/opengl/ext/EXT_debug_label.cpp 
 - src/lime/utils/_Int8Array/Int8Array_Impl_.cpp 
 - src/lime/app/_Event_Int_lime_ui_JoystickHatPosition_Void.cpp  [haxe,release]
 - src/lime/ui/_ScanCode/ScanCode_Impl_.cpp 
 - src/lime/media/openal/_ALFilter/ALFilter_Impl_.cpp 
 - src/lime/utils/_Assets/LibrarySymbol.cpp  [haxe,release]
 - src/lime/graphics/opengl/ext/EXT_texture_filter_anisotropic.cpp 
 - src/Date.cpp 
 - src/lime/media/OpenALAudioContext.cpp  [haxe,release]
 - src/lime/graphics/opengl/ext/ANGLE_texture_compression_dxt5.cpp 
 - src/lime/app/_Event_lime_ui_GamepadButton_Void.cpp  [haxe,release]
 - src/lime/app/_Event_lime_ui_GamepadAxis_Float_Void.cpp  [haxe,release]
 - src/lime/system/JNIMethod.cpp  [haxe,release]
 - src/lime/media/AudioManager.cpp  [haxe,release]
 - src/haxe/io/Eof.cpp 
 - src/lime/graphics/opengl/ext/OES_EGL_image_external.cpp 
 - src/lime/_internal/format/PNG.cpp  [haxe,release]
 - src/lime/media/openal/_ALDevice/ALDevice_Impl_.cpp 
 - src/lime/utils/_Bytes/Bytes_Impl_.cpp 
 - src/lime/ui/Gamepad.cpp  [haxe,release]
 - src/lime/graphics/opengl/ext/EXT_multisampled_render_to_texture.cpp 
 - src/lime/graphics/opengl/ext/EXT_texture_type_2_10_10_10_REV.cpp 
 - src/lime/net/_HTTPRequest_lime_graphics_Image.cpp  [haxe,release]
 - src/lime/graphics/opengl/ext/ARM_rgba8.cpp 
 - src/haxe/ds/_List/ListNode.cpp 
 - src/haxe/Unserializer.cpp 
 - src/lime/graphics/RenderContext.cpp 
 - src/lime/utils/_UInt32Array/UInt32Array_Impl_.cpp 
 - src/lime/utils/Log.cpp  [haxe,release]
 - src/haxe/ds/List.cpp 
 - src/hx/concurrent/lock/RLock.cpp 
 - src/lime/app/_Event_Float_Float_lime_ui_MouseButton_Void.cpp  [haxe,release]
Error: RLock.cpp
./src/hx/concurrent/lock/RLock.cpp(45): error C2259: 'hx::concurrent::lock::RLock_obj': cannot instantiate abstract class
include\hx/concurrent/lock/RLock.h(21): note: see declaration of 'hx::concurrent::lock::RLock_obj'
./src/hx/concurrent/lock/RLock.cpp(45): note: due to following members:
./src/hx/concurrent/lock/RLock.cpp(45): note: 'bool hx::concurrent::lock::AbstractAcquirable_obj::tryAcquire(int)': is abstract
include\hx/concurrent/lock/AbstractAcquirable.h(48): note: see declaration of 'hx::concurrent::lock::AbstractAcquirable_obj::tryAcquire'
./src/hx/concurrent/lock/RLock.cpp(45): error C2259: 'hx::concurrent::lock::RLock_obj': cannot instantiate abstract class
include\hx/concurrent/lock/RLock.h(21): note: see declaration of 'hx::concurrent::lock::RLock_obj'
./src/hx/concurrent/lock/RLock.cpp(45): note: due to following members:
./src/hx/concurrent/lock/RLock.cpp(45): note: 'bool hx::concurrent::lock::AbstractAcquirable_obj::tryAcquire(int)': is abstract
include\hx/concurrent/lock/AbstractAcquirable.h(48): note: see declaration of 'hx::concurrent::lock::AbstractAcquirable_obj::tryAcquire'
./src/hx/concurrent/lock/RLock.cpp(51): error C2259: 'hx::concurrent::lock::RLock_obj': cannot instantiate abstract class
include\hx/concurrent/lock/RLock.h(21): note: see declaration of 'hx::concurrent::lock::RLock_obj'
./src/hx/concurrent/lock/RLock.cpp(51): note: due to following members:
./src/hx/concurrent/lock/RLock.cpp(51): note: 'bool hx::concurrent::lock::AbstractAcquirable_obj::tryAcquire(int)': is abstract
include\hx/concurrent/lock/AbstractAcquirable.h(48): note: see declaration of 'hx::concurrent::lock::AbstractAcquirable_obj::tryAcquire'
./src/hx/concurrent/lock/RLock.cpp(189): error C2259: 'hx::concurrent::lock::RLock_obj': cannot instantiate abstract class
include\hx/concurrent/lock/RLock.h(21): note: see declaration of 'hx::concurrent::lock::RLock_obj'
./src/hx/concurrent/lock/RLock.cpp(189): note: due to following members:
./src/hx/concurrent/lock/RLock.cpp(189): note: 'bool hx::concurrent::lock::AbstractAcquirable_obj::tryAcquire(int)': is abstract
include\hx/concurrent/lock/AbstractAcquirable.h(48): note: see declaration of 'hx::concurrent::lock::AbstractAcquirable_obj::tryAcquire'
./src/hx/concurrent/lock/RLock.cpp(334): error C2259: 'hx::concurrent::lock::RLock_obj': cannot instantiate abstract class
include\hx/concurrent/lock/RLock.h(21): note: see declaration of 'hx::concurrent::lock::RLock_obj'
./src/hx/concurrent/lock/RLock.cpp(334): note: due to following members:
./src/hx/concurrent/lock/RLock.cpp(334): note: 'bool hx::concurrent::lock::AbstractAcquirable_obj::tryAcquire(int)': is abstract
include\hx/concurrent/lock/AbstractAcquirable.h(48): note: see declaration of 'hx::concurrent::lock::AbstractAcquirable_obj::tryAcquire'

 *  The terminal process "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command lime build windows --connect 6001" terminated with exit code: 1. 
 *  Terminal will be reused by tasks, press any key to close it. 

Specific code fails to port to HTML5, Flash

Im trying to learn the haxe-concurrent with OpenFL and it looks like I got some porting issues. The following code is self explanatory, create a bunch of threads with random as a test. On completion the code outputs the two times so I can see if working with multithreading is even worth it with my upcoming projects.
https://github.com/FlashBacks1998/haxe-concurrent-test

package;

import hx.concurrent.atomic.AtomicInt;
import hx.concurrent.Future;
import openfl.Lib;
import hx.concurrent.collection.SynchronizedArray;
import openfl.display.Sprite;
import openfl.text.TextField;
import hx.concurrent.executor.Executor;

class Main extends Sprite
{
    var executor:Executor = Executor.create(16);
    var label:TextField;

    public function new()
    {
        super();

		executor.start();		
		trace(executor.state);

		var array = new SynchronizedArray<Float>();
		var done = new AtomicInt();
		var futures = [];

		var task = function ():Void {
			var start = Lib.getTimer();
			var rand = Math.random() * 10000;

            do {
                rand = Math.random() * 10000;
            } while (rand > 10);

			array.add(rand);
			var progress = (done.incrementAndGet()/10);

			trace("task", progress, Lib.getTimer() - start, rand);
		}

		var start = Lib.getTimer();
		trace("submitting...");
		for (i in 0...1000)
		{
			futures.push(executor.submit(task));
			trace(i);
		}

		trace("waiting...");
		var result = executor.submit(task);
		
		trace(result);

		do {
			trace(done.toString());
		} while (!result.isComplete());

		var endConcurrent = Lib.getTimer() - start;
		trace("haxe-concurrent done", endConcurrent);

		start = Lib.getTimer();
		for (i in 0...1000)
			task();

		var endNative = Lib.getTimer() - start;
		trace("native done", endNative);

        // Display times in a TextField
        label = new TextField();
        label.text = "haxe-concurrent: " + endConcurrent + " ms\nnative: " + endNative + " ms";
        label.y = 50; // Adjust the vertical position of the label
        addChild(label);

		trace(futures);
    }
}

Ports to Windows, Linux, Neko, and HL works as intended. However when porting to HTML5 none of the tasks submitted to the executor actually work. I konw this because the done value never increments. When porting to Flash (RUFFLE) I get this error message;
2024-02-01T18:39:50.345837Z ERROR ruffle_core::display_object::movie_clip: Got "Error: Error #1520: Mutex cannot be initialized." when constructing AVM2 side of movie clip of type boot_0453. When using the native Flash player (v32)

Error: Error #1502: A script has executed for longer than the default timeout period of 15 seconds.
	at Main()
	at DocumentClass()
	at ApplicationMain$/start()
	at MethodInfo-99()
	at lime.app::_Event_Void_Void/dispatch()
	at openfl.display::Preloader/display_onUnload()
	at flash.events::EventDispatcher/dispatchEventFunction()
	at flash.events::EventDispatcher/dispatchEvent()
	at openfl.display::DefaultPreloader/onLoaded()
	at openfl.display::DefaultPreloader/this_onComplete()
	at flash.events::EventDispatcher/dispatchEventFunction()
	at flash.events::EventDispatcher/dispatchEvent()
	at openfl.display::Preloader/start()
	at MethodInfo-98()
	at lime.app::_Event_Void_Void/dispatch()
	at lime.utils::Preloader/start()
	at lime.utils::Preloader/updateProgress()
	at lime.utils::Preloader/current_onEnter()

What is going on? Where is the code breaking?

Thread Pool Spin Lock

Hi,

I'm just curious why you've chosen to use a spin lock on the thread pool implementation (with a short sleep). For games, a sleep of 0.001 seconds can be a very long time.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.