EMMA Coverage Report (generated Sun Feb 05 10:43:15 CET 2012)
[all classes][de.uka.ipd.sdq.simucomframework]

COVERAGE SUMMARY FOR SOURCE FILE [SimuComDefaultRandomNumberGenerator.java]

nameclass, %method, %block, %line, %
SimuComDefaultRandomNumberGenerator.java0%   (0/2)0%   (0/19)0%   (0/350)0%   (0/67)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class SimuComDefaultRandomNumberGenerator0%   (0/1)0%   (0/17)0%   (0/292)0%   (0/58)
<static initializer> 0%   (0/1)0%   (0/7)0%   (0/4)
SimuComDefaultRandomNumberGenerator (long []): void 0%   (0/1)0%   (0/69)0%   (0/13)
access$0 (): Logger 0%   (0/1)0%   (0/2)0%   (0/1)
access$1 (SimuComDefaultRandomNumberGenerator): long 0%   (0/1)0%   (0/3)0%   (0/1)
access$2 (SimuComDefaultRandomNumberGenerator): boolean 0%   (0/1)0%   (0/3)0%   (0/1)
access$3 (SimuComDefaultRandomNumberGenerator): LinkedBlockingQueue 0%   (0/1)0%   (0/3)0%   (0/1)
access$4 (SimuComDefaultRandomNumberGenerator): IRandomStream 0%   (0/1)0%   (0/3)0%   (0/1)
dispose (): void 0%   (0/1)0%   (0/7)0%   (0/3)
initRandomSeed (long []): void 0%   (0/1)0%   (0/94)0%   (0/16)
nextArrayOfDouble (double [], int, int): void 0%   (0/1)0%   (0/19)0%   (0/3)
nextArrayOfInt (int, int, int [], int, int): void 0%   (0/1)0%   (0/21)0%   (0/3)
nextDouble (): double 0%   (0/1)0%   (0/3)0%   (0/1)
nextInt (int, int): int 0%   (0/1)0%   (0/13)0%   (0/1)
random (): double 0%   (0/1)0%   (0/42)0%   (0/8)
resetNextSubstream (): void 0%   (0/1)0%   (0/1)0%   (0/1)
resetStartStream (): void 0%   (0/1)0%   (0/1)0%   (0/1)
resetStartSubstream (): void 0%   (0/1)0%   (0/1)0%   (0/1)
     
class SimuComDefaultRandomNumberGenerator$10%   (0/1)0%   (0/2)0%   (0/58)0%   (0/10)
SimuComDefaultRandomNumberGenerator$1 (SimuComDefaultRandomNumberGenerator): ... 0%   (0/1)0%   (0/6)0%   (0/2)
run (): void 0%   (0/1)0%   (0/52)0%   (0/8)

1package de.uka.ipd.sdq.simucomframework;
2 
3import java.util.Random;
4import java.util.concurrent.LinkedBlockingQueue;
5 
6import org.apache.log4j.Logger;
7 
8import de.uka.ipd.sdq.probfunction.math.IRandomGenerator;
9 
10import de.uka.ipd.sdq.probfunction.math.apache.impl.MT19937RandomGenerator;
11import de.uka.ipd.sdq.probfunction.math.random.IRandomStream;
12import de.uka.ipd.sdq.simucomframework.variables.functions.LogNormDistFunction;
13import de.uka.ipd.sdq.simucomframework.variables.functions.NormDistFunction;
14 
15/**
16 * SimuComDefaultRandomNumberGenerator generates random numbers in a separate thread.
17 * SimuComDefaultRandomNumberGenerator currently implements the interface for
18 * random numbers needed by the prob function package. However, internally it
19 * relies on a random stream implementing the RandomStream interface from JSS.
20 *
21 * SimuComDefaultRandomNumberGenerator implements {@link RandomStream} as the
22 * functions like {@link LogNormDistFunction} and {@link NormDistFunction} in
23 * package de.uka.ipd.sdq.simucomframework.variables.functions.
24 *
25 * This class is optimized for multi-cores, thus speeding up simulation significantly for
26 * at least two cores. Here everything related to random numbers in SimuCom should be then localised, especially seed
27 * initialisation and the multi-threading stuff (which was - as always - deadlock
28 * prone while implementing). Also it locates the dependency to the [0..1] random
29 * number generator to a single place in the source (remember this needs to be
30 * changed to get away from GPL code...).
31 *
32 * @author Steffen Becker
33 *
34 */
35public class SimuComDefaultRandomNumberGenerator implements IRandomGenerator {
36 
37        private static final int MAX_PRODUCER_BUFFER_SIZE = 1000;
38        private static final Logger logger =
39                Logger.getLogger(SimuComDefaultRandomNumberGenerator.class.getName());
40        private static long streamCounter = 0;
41        private long myID;
42        private final IRandomStream rndNumberGenerator;
43        private LinkedBlockingQueue<Double> producerQueue = new LinkedBlockingQueue<Double>(MAX_PRODUCER_BUFFER_SIZE);
44        private Thread producerThread;
45        private volatile boolean finished;
46 
47        public SimuComDefaultRandomNumberGenerator(long[] randomSeed){
48                this.myID = streamCounter++; 
49                this.finished = false;
50                
51                if (logger.isDebugEnabled()) {
52                        logger.debug("Initialising random number generator! [Stream ID = "+myID+"]");
53                }
54                rndNumberGenerator = new MT19937RandomGenerator();//new MRG32k3aRandomGenerator();
55                initRandomSeed(randomSeed);
56                
57                this.producerThread = new Thread(new Runnable(){
58                        public void run() {
59                                logger.debug("Random number producer started! [Stream ID = "+myID+"]");
60                                try {
61                                        while (!finished) {
62                                                producerQueue.put(rndNumberGenerator.nextDouble());
63                                        }
64                                } catch (InterruptedException e) {
65                                        logger.debug("Bad concurrency problem",e);
66                                        throw new RuntimeException("Unexpected interruption of concurrent threads");
67                                }
68                                logger.debug("Random number producer stopped! [Stream ID = "+myID+"]");
69                        }
70                });
71                producerThread.start();
72                
73                if (logger.isDebugEnabled()) {
74                        logger.debug("Random number stream initialised! [Stream ID = "+myID+"]");
75                }
76        }
77 
78        /**
79         * Set up seed of random number generator
80         * @param randomSeed The random number generator's seed. May be null for default initialisation
81         */
82        private void initRandomSeed(long[] randomSeed) {
83                if (randomSeed != null) {
84                        if (randomSeed.length == 6) {
85                                if (logger.isDebugEnabled()) {
86                                        logger.debug("Setting fixed seed for random number generator! [Stream ID = "+myID+"]");
87                                        for (int i=0; i<6; i++) {
88                                                logger.debug("Seed "+i+" = "+randomSeed[i]);
89                                        }
90                                }
91                                rndNumberGenerator.setSeed(randomSeed);
92                        }
93                        else {
94                                throw new RuntimeException("Seed array must have length of six longs for initialising random number generator");
95                        }
96                }
97                else {
98                        if (logger.isDebugEnabled()) {
99                                logger.debug("Setting random seed for random number generator! [Stream ID = "+myID+"]");
100                        }
101                        long[] myRandomSeed = new long[6];
102                        Random r = new Random();
103                        for (int i = 0; i < myRandomSeed.length; i++) {
104                                myRandomSeed[i] = r.nextInt();
105                        }
106                        rndNumberGenerator.setSeed(myRandomSeed);
107                }
108        }
109 
110        /**
111         * Returns a (pseudo)random number from the uniform distribution over the interval (0, 1), using this stream, after advancing its state by one step. The generators programmed in SSJ never return the values 0 or 1.
112         * This method takes a previously generated random number from the asynchronously running generator thread.
113         */
114        public double random() {
115                if (logger.isDebugEnabled()) {
116                        logger.debug("Drawing a random number from random number stream ["+myID+"]!");
117                }
118                double d;
119                try {
120                        d = producerQueue.take();
121                } catch (InterruptedException e) {
122                        throw new RuntimeException("Unexpected interruption of concurrent threads");
123                }
124                if (logger.isDebugEnabled()) {
125                        logger.debug("Number is: "+d);
126                }
127                return d;
128        }
129 
130        public void dispose() {
131                finished = true;
132                producerQueue.clear();
133        }
134 
135        /**
136         * Generates n (pseudo)random numbers from the uniform distribution and stores them into the array u starting at index start.
137         * (doc from {@link RandomStream})
138         * @param u - array that will contain the generated uniforms
139         * @param start - starting index, in the array u, to write uniforms from
140         * @param n - number of uniforms to generate
141         */
142        public void nextArrayOfDouble(double[] u, int start, int n) {
143                for (int i = start; i < u.length && i - start < n; i++) {
144                        u[i] = this.random();
145                }
146        }
147 
148        /**
149         * Generates n (pseudo)random numbers from the discrete uniform distribution over the
150         * integers {i, i + 1,..., j}, using this stream and stores the result in the
151         * array u starting at index start. (Calls nextInt n times.)
152         * (doc from {@link RandomStream}
153     * @param i - smallest integer that can be generated
154     * @param j - greatest integer that can be generated
155     * @param u - array that will contain the generated values
156     * @param start - starting index, in the array u, to write integers from
157     * @param n - number of values being generated
158         */
159        public void nextArrayOfInt(int i, int j, int[] u, int start,
160                        int n) {
161                for (int index = start; index < u.length && index - start < n; index++) {
162                        u[index] = this.nextInt(i, j);
163                }
164        }
165 
166        /**
167         * Returns a (pseudo)random number from the uniform distribution over the interval (0, 1), using this stream, after advancing its state by one step. The generators programmed in SSJ never return the values 0 or 1.
168         * Calls random() which takes a previously generated random number from the asynchronously running generator thread.
169         */
170        public double nextDouble() {
171                return this.random();
172        }
173 
174        /**
175         * Returns a (pseudo)random number from the discrete uniform distribution over the integers {i, i + 1,..., j}, using this stream. (Calls nextDouble once.)
176         * Copied from {@link RandomStreamBase}.
177     * @param i - smallest integer that can be generated
178     * @param j - greatest integer that can be generated
179         */
180        public int nextInt(int i, int j) {
181                // copied from RandomStreamBase
182                return i + (int)(nextDouble() * (j - i + 1.0));
183        }
184 
185        /**
186         * does nothing because this implementation does not support any substreams
187         */
188        public void resetNextSubstream() {
189        }
190 
191        /**
192         * does nothing because this implementation does not support any substreams
193         */
194        public void resetStartStream() {
195        }
196 
197 
198        /**
199         * does nothing because this implementation does not support any substreams
200         */
201        public void resetStartSubstream() {
202        }
203 
204}

[all classes][de.uka.ipd.sdq.simucomframework]
EMMA 2.0.9414 (unsupported private build) (C) Vladimir Roubtsov