All Projects → iCodeSometime → Asynchronize

iCodeSometime / Asynchronize

Licence: mit
A declarative syntax for creating asynchronous methods.

Programming Languages

ruby
36898 projects - #4 most used programming language

Projects that are alternatives of or similar to Asynchronize

Fbg
Lightweight C 2D graphics API agnostic library with parallelism support
Stars: ✭ 349 (+897.14%)
Mutual labels:  multithreading, lightweight
Thread Loader
Runs the following loaders in a worker pool
Stars: ✭ 945 (+2600%)
Mutual labels:  multithreading
Lightcomm4j
Yet another lightweight asynchronous network library for java
Stars: ✭ 25 (-28.57%)
Mutual labels:  lightweight
Ostrio Analytics
📊 Visitor's analytics tracking code for ostr.io service
Stars: ✭ 9 (-74.29%)
Mutual labels:  lightweight
Cross
Cross++ Lightweight Crossplatform Game Engine
Stars: ✭ 26 (-25.71%)
Mutual labels:  lightweight
Ppipe
A simple and lightweight Rust library for making iterator pipelines concurrent
Stars: ✭ 13 (-62.86%)
Mutual labels:  multithreading
Vertx Embedded Springboot
Vert.x embeded Springboot
Stars: ✭ 19 (-45.71%)
Mutual labels:  multithreading
Enkits
A permissively licensed C and C++ Task Scheduler for creating parallel programs. Requires C++11 support.
Stars: ✭ 962 (+2648.57%)
Mutual labels:  multithreading
Tcodeedit
Lightweight and syntax hilighted UNICODE editor
Stars: ✭ 27 (-22.86%)
Mutual labels:  lightweight
Puma
A Ruby/Rack web server built for parallelism
Stars: ✭ 6,924 (+19682.86%)
Mutual labels:  multithreading
Cicada
🚀 Fast lightweight HTTP service framework.
Stars: ✭ 851 (+2331.43%)
Mutual labels:  lightweight
Worker Threads Nodejs
Benchmark nodeJS worker threads for calculating prime numbers, using various dataStructures
Stars: ✭ 27 (-22.86%)
Mutual labels:  multithreading
Humblelogging
HumbleLogging is a lightweight C++ logging framework. It aims to be extendible, easy to understand and as fast as possible.
Stars: ✭ 15 (-57.14%)
Mutual labels:  lightweight
Jpegrtspcamera
Sample RTSP server streaming MJPEG video from PC camera
Stars: ✭ 25 (-28.57%)
Mutual labels:  multithreading
Zeus
A high performance, cross-platform Internet Communication Engine. Developed with native socket API. Aim at handling millions of concurrent connections.
Stars: ✭ 30 (-14.29%)
Mutual labels:  multithreading
Larastrator
All in one - admin panel with tailwindcss and vuejs.
Stars: ✭ 25 (-28.57%)
Mutual labels:  lightweight
Broken
Lightweight Unit Testing for C++
Stars: ✭ 8 (-77.14%)
Mutual labels:  lightweight
Lib
single header libraries for C/C++
Stars: ✭ 866 (+2374.29%)
Mutual labels:  multithreading
Onloaded
A tiny (350B) library to detect when images have loaded.
Stars: ✭ 33 (-5.71%)
Mutual labels:  lightweight
Lightweight Human Pose Estimation.pytorch
Fast and accurate human pose estimation in PyTorch. Contains implementation of "Real-time 2D Multi-Person Pose Estimation on CPU: Lightweight OpenPose" paper.
Stars: ✭ 958 (+2637.14%)
Mutual labels:  lightweight

Build Status Maintainability Test Coverage

Asynchronize

A declarative syntax for creating asynchronous methods.

Find yourself writing the same boilerplate for all your asynchronous methods? Get dry with asynchronize.

Just add to your Gemfile and bundle or install globally with gem install asynchronize

Usage

Create a class with asynchronized methods

require 'asynchronize'
class Test
  include Asynchronize
  # Can be called before or after method definitions. I prefer it at the top of classes.
  asynchronize :my_test, :my_other_test
  def my_test
    return 'testing'
  end
  def my_other_test
    #do stuff here too
  end
end

Now, to call those methods.

The method's return value can be accessed either with Thread#value or through the thread param :return_value (make sure the thread is finished first!)

thread = Test.new.my_test
puts thread.value          # > testing
puts thread[:return_value] # > testing

Or if called with a block, the method's return value will be passed as a parameter. In this case, the original function's return value is still accessible at :return_value, and Thread#value contains the value returned from the block.

thread = Test.new.my_test do |return_value|
  return_value.length
end
puts thread.value          # > 7
puts thread[:return_value] # > testing

As you can see, it's just a regular thread. Make sure you call either Thread#value orThread#join to ensure it completes before your process exits, and to catch any exceptions that may have been thrown!

Inspiration

While working on another project, I found myself writing this way too often:

def method_name(args)
  Thread.new(args) do |targs|
    # Actual code.
  end
end

It's extra typing, and adds an unneeded extra layer of nesting. I couldn't find an existing library that wasn't trying to add new layers of abstraction I didn't need; sometimes you just want a normal thread. Now, just call asynchronize to make any method asynchronous.

Versioning Policy

Beginning with version 1.0.0, this project will follow Semantic Versioning. Until then, the patch number (0.0.x) will be updated for any changes that do not affect the public interface. Versions that increment the minor number (0.x.0) will have at least one of the following. A new feature will be added, some feature will be deprecated, or some previously deprecated feature will be removed. Deprecated features will be removed on the very next version that increments the minor version number.

FAQ

Doesn't metaprogramming hurt performance?

Not at all! What we're doing in this project actually works exactly like inheritance, so it won't be a problem.

So, how does it work?

When you include Asynchronize it creates an asynchronize method on your class.

require 'asynchronize'
class Test
  include Asynchronize
end
Test.methods - Object.methods # > [:asynchronize]

The first time you call this method with any arguments, it creates a new module with the methods you define. It uses Module#prepend to insert itself at the top of the class's inheritance chain. This means that its methods are called before the class's own methods.

class Test
  asynchronize :my_test
  def my_test
    return 'testing'
  end
end

Test.constants # > [:Asynchronized]
Test::Asynchronized.instance_methods # > [:my_test]
Test.ancestors # > [Test::Asynchronized, Test, Asynchronize, Object, Kernel, BasicObject]

Where the implementation of Test::Asynchronized#my_test (and any other method) is like

return Thread.new(args, block) do |thread_args, thread_block|
  Thread.current[:return_value] = super(*thread_args)
  next thread_block.call(Thread.current[:return_value]) if thread_block
  Thread.current[:return_value]
end

This implementation allows you to call asynchronize at the top of the class and then define the methods below. Since it changes how you interact with those method's return values, I thought it was important to allow this.

Why do I need another gem? My code's bloated enough as it is?

It's super tiny. Just a light wrapper around the existing language features. Seriously, it's just around forty lines of code. Actually, according to cloc there's almost four times as many lines in the tests as the source. You should read it. I'd love feedback!

Do you accept contributions?

Absolutely!

  1. Fork it (https://github.com/kennycoc/asynchronize/fork)
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new pull request.

It's just bundle to install dependencies, and rake to run the tests.

What's the difference between asynchronize and promises/async..await?

Those and other similar projects aim to create an entirely new abstraction to use for interacting with threads. This project aims to be a light convenience wrapper around the existing language features. Just define a regular method, then interact with its result like a regular thread.

What Ruby versions are supported?

Ruby 2.3 and up. Unfortunately, Ruby versions prior to 2.0 do not support Module#prepend and are not supported. Ruby versions prior to 2.3 have a bug preventing usage of super with define_method. I'm unable to find a suitable workaround for this issue. (method(__method__).super_method.call causes problems when a method inherits from the asynchronized class.)

Luckily, all major Ruby implementations support Ruby language version 2.3, so I don't see this as a huge problem. If anyone wants support for older versions, and knows how to work around this issue, feel free to submit a pull request.

We explicitly test against the following versions:

  • Matz Ruby 2.6.0
  • Matz Ruby 2.3.8
  • JRuby 9.2.5.0 (ruby language version 2.5.x)
  • Rubinius 3.100 (ruby language version 2.3.1)

Is it any good?

Yes

Does anyone like it?

License

MIT

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].