views:

107

answers:

5

This is my scenario.

I have a pool of frequencies and my BaseStation needs to select one of them. The critical section for a BaseStation is the phase when it goes into frequency selection. Once it selects frequencies, control returns back to the main BaseStation class and it resumes its request generation. At the same time, i.e. as soon as it exits its critical section, the frequency that was selected will go into a use state for a certain period of time, that will be decided by the random clock. So this frequency will be unavailable for any other request that happens in the interim. Once, the frequency use time is over, it just sets its status as available again. So the mutual exclusion part for the BaseStation is only for frequency selection, once that's over, the BaseStation functionality and the frequency use time run parallely.

How I've coded so far is: I have three classes BaseStation, CriticalSection and UseFrequency. BaseStation calls a function in CriticalSection for frequency selection, once the frequency is selected I have a function that starts a thread in another class for frequency use and then returns control to BaseStation soon after:

UseFrequency freqInUse = new UseFrequency; 
freqInUse.start(); 
return 1; 

But once the thread stops, the class CriticalSection needs some variables updated, I'm confused how to return control back to the middle class. Would I need to use two threads?

A: 

Now I understand the question. Using the observable pattern would be a good way to do this. Here's an example I like from Javaworld: http://www.javaworld.com/javaworld/javatips/jw-javatip29.html

SOA Nerd
+4  A: 

I'm not sure what your question is (so I've kind of guessed!) but one option would be to wrap the Apache GenericObjectPool to store your Frequency objects and call borrowObject() to remove a Frequency from the pool and indicate that it is "in use". Upon calling borrowObject() you could also schedule a task (e.g. with a ScheduledExecutorService) to call returnObject() at some point in the future, thus making the Frequency available again to other threads.

public class FrequencyPool {
  private final GenericObjectPool objPool = ...
  private final ScheduledExecutorService timerService = ...
  private final Random random = new Random();

  public Frequency takeFrequency() {
    final Frequency freq = (Frequency) objPool.borrowObject(); // Will block

    // Return frequency to underlying object pool after a random time.
    timerService.schedule(new Callable<Void>{
      public Void call() {
        objPool.returnObject(freq);
      }
    }, random.nextInt(10), TimeUnit.SECONDS);

    return freq;
  }
}
Adamski
+1  A: 

Keep an array of the frequencies, and another array of the state of the frequencies that is, whether used or unused. You need a read-write lock to access the frequencies. Once a frequency is started to be in use the state of the frequency can be set to used, start a timer which triggers a change that acquires the write-lock, and changes the frequency state back to unused.

Amit Kumar
+2  A: 

The simplest way to control concurrency for something like this is probably a ReadWriteLock (ReentrantReadWriteLock is the implementation). While frequency selection is occurring, you should lock the write lock and then unlock when done. Normal usage would just obtain read locks. This provides mutual exclusion during frequency selection but concurrent use otherwise.

A more generic solution with more fine-grained control over a pooled set of resources could be built with a Semaphore.

Alex Miller
A: 

For you to return control back to the calling critical section class use Executor to execute your thread.Eg:

Blockquote ExecutorService executor = Executors.newSingleThreadExecutor();

    Future<?> future = executor.submit(//submit frequency thread runnable object);

    try {
        future.get();
        //do critical section update
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (ExecutionException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    executor.shutdown();