Support This Project

About RJL

RJL stand's for RJ's language. It is a long running and little progressed project to construct a better programming language. The current idea is to construct a programing language with the aesthetics of ruby that allows for static typing, a virtual machine, and dynamic typing.

Here are links to other rambings about RJL.

The first step is to construct some programs to demonstrate how the language works. There are two aspects to such programs, the code and the translation into class files for loading into a VM.

So lets jump right in and look at the design of a resource pool for a multithreaded environment. This will serve to illustrate the syntax, and by some explaination, and also by some similarity to existing languages, serve to illuminate the semantics.

  // this is a comment
  class 'a ResourcePool

    // following a fields that get initialised, one is an array
    // the other is a hash table (a mapping)
    _free_list = []
    _allocated = {}

    // this is an inner class. Inner classes in RJL don't have parent
    // pointers because that is a java cludge.
    class UnallocatedResourceReleased
      // inheritance is specified with extends
      :extends PreconditionFailure
    end

    // the initialize method is called from class.new method
    def initialize(n: Int)
      for i in 1..n do
        r = yield(i)
        _free_list << r
      end
    end

    // by default methods are public and unsynchronised
    def get_resource: 'a
      :private, :synchronized 
      while free_list.is_empty { self.wait }
      i = _free_list.pop
      return _resources[i]
    end

    // when no return type is specified then the function
    // has no return value
    def release_resource(resource: 'a)
      :private, :synchronised
      if ! _allocated.is_member(a) then
        throw UnallocatedResourceReleased.new
      else
        _allocated.remove(a)
        _free_list.push(_resource)
        self.notify
      end
    end

    // if a method makes a call to yield then it may accept
    // a block as the last argument
    def with
      r = get_resource
      begin
        yield(r)
      finally
        // the finally block is always called, no exceptions
	// (cept maybe if the machine is turned off or the process
	// gets viciously killed).
        release_resource(r)
      end
    end
  end

  class ResourcePoolUnitTest
    :extends UnitTest

    def test_two_threads
      pool = ResourcePool.new 5, { i | i }
      n    = 10
      xs   = Array.new_copy 0 n
      ts   = []
      for i in 1..n do
        ts = Thread.new {
          sleep(i)
          pool.with {
            | resource_id |
            xs[resource_id] = resource_id
            sleep(i)
          }
        }
      end
      begin
        for i in 1..n do
          Thread.timeout 500, { ts.wait_for_termination }
        end
      catch e: TimeoutException
        return TestFailure.new "Deadlock on thread #{i}"
      end
      for i in 1..n do
        if xs[i] != i then
          return TestFailure.new "Thread #{i} failed to set the right result."
        end
      end

      return TestSuccess
    end
  end

The unit test implemented here doesn't not test a number of error conditions. Testing or proving that deadlock cannot occur is difficult. The process does setup contension since it construct quickly 10 threads which all try to access a value from the pool. There is also a race condnition since the variable xs is not protected (assuming that Array does not have a thread safe implementation).

Thread safety is very expensive as we have seen. Even when there is a single thread obtaining a condition variable is potentially expensive.