1 /*
2  * Copyright 2016 The Netty Project
3  *
4  * The Netty Project licenses this file to you under the Apache License,
5  * version 2.0 (the "License"); you may not use this file except in compliance
6  * with the License. You may obtain a copy of the License at:
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations
14  * under the License.
15  */

16 package io.netty.util.concurrent;
17
18 import io.netty.util.internal.UnstableApi;
19
20 import java.util.concurrent.atomic.AtomicInteger;
21 import java.util.concurrent.atomic.AtomicLong;
22
23 /**
24  * Default implementation which uses simple round-robin to choose next {@link EventExecutor}.
25  */

26 @UnstableApi
27 public final class DefaultEventExecutorChooserFactory implements EventExecutorChooserFactory {
28
29     public static final DefaultEventExecutorChooserFactory INSTANCE = new DefaultEventExecutorChooserFactory();
30
31     private DefaultEventExecutorChooserFactory() { }
32
33     @Override
34     public EventExecutorChooser newChooser(EventExecutor[] executors) {
35         if (isPowerOfTwo(executors.length)) {
36             return new PowerOfTwoEventExecutorChooser(executors);
37         } else {
38             return new GenericEventExecutorChooser(executors);
39         }
40     }
41
42     private static boolean isPowerOfTwo(int val) {
43         return (val & -val) == val;
44     }
45
46     private static final class PowerOfTwoEventExecutorChooser implements EventExecutorChooser {
47         private final AtomicInteger idx = new AtomicInteger();
48         private final EventExecutor[] executors;
49
50         PowerOfTwoEventExecutorChooser(EventExecutor[] executors) {
51             this.executors = executors;
52         }
53
54         @Override
55         public EventExecutor next() {
56             return executors[idx.getAndIncrement() & executors.length - 1];
57         }
58     }
59
60     private static final class GenericEventExecutorChooser implements EventExecutorChooser {
61         // Use a 'long' counter to avoid non-round-robin behaviour at the 32-bit overflow boundary.
62         // The 64-bit long solves this by placing the overflow so far into the future, that no system
63         // will encounter this in practice.
64         private final AtomicLong idx = new AtomicLong();
65         private final EventExecutor[] executors;
66
67         GenericEventExecutorChooser(EventExecutor[] executors) {
68             this.executors = executors;
69         }
70
71         @Override
72         public EventExecutor next() {
73             return executors[(int) Math.abs(idx.getAndIncrement() % executors.length)];
74         }
75     }
76 }
77