diff --git a/.appveyor.yml b/.appveyor.yml deleted file mode 100644 index 761a279..0000000 --- a/.appveyor.yml +++ /dev/null @@ -1,41 +0,0 @@ -## Documentation: https://github.com/JuliaCI/Appveyor.jl - -environment: - # JULIA_NUM_THREADS: 4 - matrix: - - julia_version: 1.0 - - julia_version: 1.2 - - julia_version: 1.3 - - julia_version: nightly - -platform: - - x86 # 32-bit - - x64 # 64-bit - -## uncomment the following lines to allow failures on nightly julia -## (tests will run but not make your overall status red) -matrix: - allow_failures: - - julia_version: nightly - -#branches: -# only: -# - master -# - /release-.*/ - -notifications: - - provider: Email - on_build_success: false - on_build_failure: false - on_build_status_changed: false - -install: - - ps: iex ((new-object net.webclient).DownloadString("https://raw.githubusercontent.com/JuliaCI/Appveyor.jl/version-1/bin/install.ps1")) - -build_script: - - echo "%JL_BUILD_SCRIPT%" - - C:\julia\bin\julia -e "%JL_BUILD_SCRIPT%" - -test_script: - - echo "%JL_TEST_SCRIPT%" - - C:\julia\bin\julia -e "%JL_TEST_SCRIPT%" diff --git a/.github/workflows/CompatHelper.yml b/.github/workflows/CompatHelper.yml index db0a0d3..f0fa494 100644 --- a/.github/workflows/CompatHelper.yml +++ b/.github/workflows/CompatHelper.yml @@ -15,7 +15,7 @@ jobs: steps: - uses: julia-actions/setup-julia@latest with: - version: 1.3 + version: 1.4 - name: Pkg.add("CompatHelper") run: julia -e 'using Pkg; Pkg.add("CompatHelper")' - name: CompatHelper.main() diff --git a/.travis.yml b/.travis.yml index cb485ca..8ccc608 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,22 +5,28 @@ language: julia os: - linux - osx + - windows julia: - 1.0 - - 1.2 - 1.3 + - 1.4 - nightly env: + - JULIA_NUM_THREADS=1 - JULIA_NUM_THREADS=4 -## uncomment the following lines to allow failures on nightly julia -## (tests will run but not make your overall status red) -matrix: - allow_failures: - - julia: nightly - fast_finish: true +arch: + - amd64 + - x86 + +branches: + only: + - master + - dev + - /^release-.*$/ + - /^v\d+\.\d+(\.\d+)?(-\S*)?$/ notifications: email: false @@ -32,10 +38,21 @@ after_success: - julia -e 'import Pkg; Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())' jobs: + allow_failures: + # - julia: nightly + - os: windows + julia: 1.0 + env: JULIA_NUM_THREADS=4 + fast_finish: true + exclude: + # To recuce number of tests: + - arch: x86 + env: JULIA_NUM_THREADS=1 include: - stage: "Documentation" - julia: 1.0 + julia: 1.4 os: linux + arch: amd64 script: - julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()' - julia --project=docs/ docs/make.jl diff --git a/Project.toml b/Project.toml index 99174dd..a554c3c 100644 --- a/Project.toml +++ b/Project.toml @@ -4,6 +4,7 @@ version = "0.4.1" [deps] Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b" +MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" [compat] julia = "1" diff --git a/README.md b/README.md index 8d599f4..46ebcaf 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,6 @@ [![Documentation for development version](https://img.shields.io/badge/docs-dev-blue.svg)](https://oschulz.github.io/ParallelProcessingTools.jl/dev) [![License](http://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)](LICENSE.md) [![Travis Build Status](https://travis-ci.com/oschulz/ParallelProcessingTools.jl.svg?branch=master)](https://travis-ci.com/oschulz/ParallelProcessingTools.jl) -[![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/github/oschulz/ParallelProcessingTools.jl?branch=master&svg=true)](https://ci.appveyor.com/project/oschulz/ParallelProcessingTools-jl) [![Codecov](https://codecov.io/gh/oschulz/ParallelProcessingTools.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/oschulz/ParallelProcessingTools.jl) This Julia package provides some tools to ease multithreaded and distributed programming, especially for more complex use cases and when using multiple processes with multiple threads on each process. It also provides functions and macros designed to ease the transition to the new multi-threading model introduced in Julia v1.3. diff --git a/docs/Project.toml b/docs/Project.toml index b691818..2307a07 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -3,4 +3,4 @@ Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a" [compat] -Documenter = "~0.23" +Documenter = "~0.24" diff --git a/docs/make.jl b/docs/make.jl index 71139fe..2cca2df 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -14,7 +14,7 @@ makedocs( prettyurls = !("local" in ARGS), canonical = "https://oschulz.github.io/ParallelProcessingTools.jl/stable/" ), - pages=[ + pages = [ "Home" => "index.md", "API" => "api.md", "LICENSE" => "LICENSE.md", @@ -26,5 +26,6 @@ makedocs( deploydocs( repo = "github.com/oschulz/ParallelProcessingTools.jl.git", - forcepush = true + forcepush = true, + push_preview = true, ) diff --git a/src/ParallelProcessingTools.jl b/src/ParallelProcessingTools.jl index 6c3f3ba..6f09ec4 100644 --- a/src/ParallelProcessingTools.jl +++ b/src/ParallelProcessingTools.jl @@ -7,6 +7,8 @@ module ParallelProcessingTools using Base.Threads using Distributed +using MacroTools + include("threadsafe.jl") include("threadlocal.jl") include("onthreads.jl") diff --git a/src/onthreads.jl b/src/onthreads.jl index f85631a..67c998c 100644 --- a/src/onthreads.jl +++ b/src/onthreads.jl @@ -180,7 +180,7 @@ export @onthreads macro onallthreads(expr) quote - Base.depwarn("`@onallthreads expr` is deprecated, use `@onallthreads allthreads() expr` instead.", nothing) + Base.depwarn("`@onallthreads expr` is deprecated, use `@onthreads allthreads() expr` instead.", nothing) $(_thread_exec_func(:(ParallelProcessingTools.allthreads()), expr)) end end @@ -223,3 +223,57 @@ macro mt_async(expr) end end export @mt_async + + +using MacroTools +""" + @mt_out_of_order begin expr... end + +Runs all top-level expressions in `begin expr... end` on parallel tasks. +On Julia >= v1.3, the tasks will run multi-threaded. + +Example: + +``` +@mt_out_of_order begin + a = foo() + bar() + c = baz() +end + +will run `a = foo()`, `bar()` and `c = baz()` in parallel and in arbitrary +order, results of assignments will appear in the outside scope. +""" +macro mt_out_of_order(ex) + if !(ex isa Expr && ex.head == :block) + throw(ErrorException("@mt_out_of_order expects a code block as it's argument")) + end + + exprs = ex.args + idxs = eachindex(ex.args) + tasks = gensym(:tasks) + handle_results = Vector{Expr}() + for i in idxs + trg = nothing; val = nothing; + if @capture(exprs[i], trg_ = val_) + if val isa Expr + exprs[i] = :(push!($tasks, @mt_async($(esc(val))))) + push!(handle_results, :($(esc(trg)) = fetch(popfirst!($tasks)))) + else + exprs[i] = esc(exprs[i]) + end + elseif exprs[i] isa Expr + ftvar = gensym() + exprs[i] = :(push!($tasks, @mt_async($(esc(exprs[i]))))) + push!(handle_results, :(wait(popfirst!($tasks)))) + else + exprs[i] = esc(exprs[i]) + end + end + pushfirst!(exprs, :($tasks = Vector{Task}())) + append!(exprs, handle_results) + push!(exprs, :(@assert isempty($tasks))) + push!(exprs, :nothing) + ex +end +export @mt_out_of_order diff --git a/test/test_onthreads.jl b/test/test_onthreads.jl index 7f854dd..0a186c0 100644 --- a/test/test_onthreads.jl +++ b/test/test_onthreads.jl @@ -49,6 +49,23 @@ using Base.Threads end end + @testset "macro mt_out_of_order" begin + @test begin + b = 0 + foo() = b = 9 + bar() = 33 + + @mt_out_of_order begin + a = (sleep(0.05); 42) + foo() + c::Int = bar() + + d = :trivial + end + (a, b, c, d) == (42, 9, 33, :trivial) + end + end + @testset "Examples" begin @testset "Example 1" begin tlsum = ThreadLocal(0.0)