# SyncEm: Thread-Safe Decorators in Ruby

Source: https://www.yegor256.com/2019/06/26/syncem.html

I wrote some time ago about thread-safety in OOP and how it can
be achieved with [decorators]({% pst 2017/jan/2017-01-17-synchronized-decorators %}).
It was also said that it's very important to make sure objects are thread-safe
([in Ruby]({% pst 2018/nov/2018-11-06-ruby-threads %}) and
[in Java]({% pst 2018/mar/2018-03-27-how-to-test-thread-safety %})),
especially in web apps, which are multi-threaded (well, in most
cases anyway). Well, here is [SyncEm](https://github.com/yegor256/syncem),
a primitive Ruby gem which makes the above possible with a single decorator.


Look at this simple Ruby web app, which increments the internal counter
on every web click:

```ruby
require 'sinatra'
class Front < Sinatra::Base
  configure do
    set(:visits, Visits.new)
  end
  before '/*' do
    settings.visits.increment
  end
  get '/' do
    "Your visit is no.#{settings.visits.total}"
  end
end
Front.run!
```

In order to count visits it uses class `Visits`, which may be
defined this way (it keeps the counter in a file):

```ruby
class Visits
  def increment
    idx = IO.read('idx.txt').to_i + 1
    IO.write('idx.txt', idx.to_s)
    idx.to_s
  end
  def total
    IO.read('idx.txt').to_i
  end
end
```

It is not thread-safe. Try to run this app and you will see that,
if you make many concurrent HTTP requests to the front page,
the counter will not always return consecutive numbers.

To make it thread-safe you can use [SyncEm](https://github.com/yegor256/syncem),
a small Ruby gem, which I created just a few months ago. Here is how:

```ruby
require 'syncem'
class Front < Sinatra::Base
  configure do
    set(:visits, SyncEm.new(Visits.new))
  end
  # Same as above
end
```

Here we just _decorate_ the object with a thread-safe decorator, which
intercepts all calls to all methods of an object and make them all
synchronized with a single encapsulated semaphore:

```ruby
SyncEm.new(Visits.new)
```

This mechanism will only work in Ruby or similar
[interpreted](https://en.wikipedia.org/wiki/Interpreted_language) languages.
I would not be able to do the same in Java or C++. But in Ruby, Python,
PHP, JavaScript and many others, similar decorators may be very useful.

I'm using it in [this web app](https://github.com/zold-io/wts.zold.io), for example.
