Code360 powered by Coding Ninjas X Naukri.com. Code360 powered by Coding Ninjas X Naukri.com
Table of contents
1.
Introduction
2.
Delaying and Repeating Execution: after and every
3.
Thread Safety with Synchronized Blocks
4.
Frequently Asked Questions
4.1.
What is Ruby?
4.2.
What are the uses of Ruby?
5.
Conclusion
Last Updated: Mar 27, 2024

Custom Control Structures In Ruby

Author Ankit kumar
0 upvote

Introduction

Ruby’s use of blocks, coupled with its parentheses-optional syntax, make it very easy to define iterator methods that look like and behave like control structures. One simple example is the loop method of the kernel. In this article, we will discuss some examples that uses ruby’s threading API. 

Delaying and Repeating Execution: after and every

#
# Define Kernel methods after and every for deferring blocks of code.
# Examples: 
# 
# after 1 { puts "done" } 
# every 60 { redraw_clock } 
#
# Both methods return Thread objects. Call kill on the returned objects 
# to cancel the execution of the code. 
# 
# Note that this is a very naive implementation. A more robust # implementation would use a      single global timer thread for all tasks, 
# would allow a way to retrieve the value of a deferred block, and would 
# provide a way to wait for all pending tasks to complete. 
# 
# Execute block after sleeping the specified number of seconds. def after(seconds, &block) Thread.new do    # In a new thread... 
sleep(seconds)   # First sleep 
block.call            # Then call the block
  end     # Return the Thread object right away 
end 

# Repeatedly sleep and then execute the block. 
# Pass value to the block on the first invocation. 
# On subsequent invocations, pass the value of the previous invocation. 
def every(seconds, value=nil, &block) 
    Thread.new do           # In a new thread... 
        loop do                  # Loop forever (or until break in block) 
            sleep(seconds) # Sleep 
            value = block.call(value) # And invoke block 
            end # Then repeat.. 
        end # every returns the Thread 
end

The example above contains global methods named after and every. Each takes a numeric argument that represents a number of seconds and should have a block associated with it. after creates a new thread and returns the Thread object immediately. The newly created thread sleeps for the specified number of seconds and then calls (with no arguments) the block you provided. every is similar, but it calls the block repeatedly, sleeping the specified number of seconds between calls. The second argument to every is a value to pass to the first invocation of the block. The return value of each invocation becomes the value passed for the next invocation. The block associated with every can use break to prevent any future invocations.

Thread Safety with Synchronized Blocks

When writing programs that use multiple threads, it is important that two threads do not attempt to modify the same object at the same time. One way to do this is to place the code that must be made thread-safe in a block associated with a call to the synchronize method of a Mutex object.\In Example below, we take this a step further, and emulate Java’s synchronized keyword with a global method named synchronized. This synchronized method expects a single object argument and a block. It obtains a Mutex associated with the object, and uses Mutex.synchronize to invoke the block. The tricky part is that Ruby’s object, unlike Java’s objects, do not have a Mutex associated with them. So below Example also defines an instance method named mutex in Object. Interestingly, the implementation of this mutex method uses synchronized in its new keyword-style form!

require 'thread'      # Ruby 1.8 keeps Mutex in this library 
# Obtain the Mutex associated with the object o, and then evaluate 
# the block under the protection of that Mutex. 
# This works like the synchronized keyword of Java. 
def synchronized(o) o.mutex.synchronize { yield } 
end 
# Object.mutex does not actually exist. We've got to define it. 
# This method returns a unique Mutex for every object, and 
# always returns the same Mutex for any particular object.
# It creates Mutexes lazily, which requires synchronization for
# thread safety.
class Object 
# Return the Mutex for this object, creating it if necessary. 
# The tricky part is making sure that two threads don't call 
# this at the same time and end up creating two different mutexes. 
def mutex 
# If this object already has a mutex, just return it 
return @__mutex if @__mutex
# Otherwise, we've got to create a mutex for the object. 
# To do this safely we've got to synchronize on our class object.
synchronized(self.class) { 
# Check again: by the time we enter this synchronized block, 
# some other thread might have already created the mutex. 
@__mutex = @__mutex || Mutex.new 
} 
# The return value is @__mutex 
end 
end 
# The Object.mutex method defined above needs to lock the class 
# if the object doesn't have a Mutex yet. If the class doesn't have 
# its own Mutex yet, then the class of the class (the Class object) 
# will be locked. In order to prevent infinite recursion, we must 
# ensure that the Class object has a mutex. 
Class.instance_eval { @__mutex = Mutex.new }

Frequently Asked Questions

What is Ruby?

Ruby is an open-source dynamic and object-oriented programming language. It is an interpreted language that means source code is compiled by an interpreter at the time of execution.

What are the uses of Ruby?

Ruby is generally used for building web applications. It is a general-purpose programming language and finds many applications in data analysis, prototyping, and proof of concept.

Conclusion

In this article,we discussed about ruby,and its custom control structure.

Refer to our Guided Path on Coding Ninjas Studio to upskill yourself in Data Structures and AlgorithmsCompetitive ProgrammingJavaScriptSystem DesignMachine learning and many more! If you want to test your competency in coding, you may check out the mock test series and participate in the contests hosted on Coding Ninjas Studio! But if you have just started your learning process and are looking for questions asked by tech giants like Amazon, Microsoft, Uber, etc; you must look at the problemsinterview experiences, and interview bundle for placement preparations.

Nevertheless, you may consider our paid courses to give your career an edge over others!

Do upvote our blogs if you find them helpful and engaging!

Happy Learning!!

Thank You
Live masterclass