1   /*
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2026, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v2.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  
15  package ch.qos.logback.core.blackbox;
16  
17  //import ch.qos.logback.core.Appender;
18  //import ch.qos.logback.core.AppenderBase;
19  //import ch.qos.logback.core.Context;
20  //import ch.qos.logback.core.ContextBase;
21  //import ch.qos.logback.core.spi.AppenderAttachableImpl;
22  import org.junit.jupiter.api.Disabled;
23  //import org.junit.jupiter.api.Test;
24  //
25  //import java.util.concurrent.ExecutionException;
26  //import java.util.concurrent.ExecutorService;
27  //import java.util.concurrent.Executors;
28  //
29  //import java.util.ArrayList;
30  //import java.util.Arrays;
31  //import java.util.List;
32  //import java.util.concurrent.Future;
33  //import java.util.concurrent.locks.ReentrantLock;
34  //
35  //import static org.assertj.core.api.Fail.fail;
36  
37  @Disabled
38  public class COWArrayListConcurrencyTest {
39  //
40  //    //private static final int LIST_SIZE = 1_000_000;
41  //    private static final int LOOP_LEN = 1_0;
42  //    private static final int RECONFIGURE_DELAY = 1;
43  //
44  //    ReentrantLock reconfigureLock = new ReentrantLock(true);
45  //    ReentrantLock writeLock = new ReentrantLock(true);
46  //
47  //    private static int THREAD_COUNT = 200; //Runtime.getRuntime().availableProcessors()*200;
48  //    //private static int THREAD_COUNT = 5000;
49  //
50  //    private final ExecutorService tasksExecutor = Executors.newVirtualThreadPerTaskExecutor();
51  //    LoopingRunnable[] loopingThreads = new LoopingRunnable[THREAD_COUNT];
52  //    ReconfiguringThread[] reconfiguringThreads = new ReconfiguringThread[THREAD_COUNT];
53  //    Future<?>[] futures = new Future[THREAD_COUNT];
54  //
55  //    AppenderAttachableImpl<String> aai = new AppenderAttachableImpl<>();
56  //    Context context = new ContextBase();
57  //
58  //    void reconfigureWithDelay(AppenderAttachableImpl<String> aai) {
59  //        try {
60  //            reconfigureLock.lock();
61  //            aai.addAppender(makeNewNOPAppender());
62  //            aai.addAppender(makeNewNOPAppender());
63  //            delay(RECONFIGURE_DELAY);
64  //            aai.detachAndStopAllAppenders();
65  //        } finally {
66  //            reconfigureLock.unlock();
67  //        }
68  //    }
69  //
70  //    private Appender<String> makeNewNOPAppender() {
71  //        List<Long> longList = new ArrayList<>();
72  ////        for (int j = 0; j < LIST_SIZE; j++) {
73  ////            longList.add(0L);
74  ////        }
75  //        Appender<String> nopAppenderWithDelay = new NOPAppenderWithDelay<>(longList);
76  //        nopAppenderWithDelay.setContext(context);
77  //        nopAppenderWithDelay.start();
78  //        return nopAppenderWithDelay;
79  //    }
80  //
81  //    private void delay(int delay) {
82  //        try {
83  //            Thread.sleep(delay);
84  //        } catch (InterruptedException e) {
85  //            throw new RuntimeException(e);
86  //        }
87  //    }
88  //
89  //    @Test
90  //    void smoke() throws InterruptedException, ExecutionException {
91  //
92  //        for (int i = 0; i < THREAD_COUNT; i++) {
93  //            System.out.println("i="+i);
94  //            ReconfiguringThread rt = new ReconfiguringThread(aai);
95  //            futures[i] = tasksExecutor.submit(rt);
96  //            reconfiguringThreads[i] = rt;
97  //        }
98  //
99  //        for (int i = 0; i < THREAD_COUNT; i++) {
100 //            LoopingRunnable loopingThread = new LoopingRunnable(i, aai);
101 //            tasksExecutor.submit(loopingThread);
102 //            loopingThreads[i] = loopingThread;
103 //        }
104 //
105 //        for (int i = 0; i < THREAD_COUNT; i++) {
106 //            futures[i].get();
107 //        }
108 //
109 //        //reconfiguringThread.join();
110 //        Arrays.stream(loopingThreads).forEach(lt -> lt.active = false);
111 //
112 //    }
113 //
114 //    public class NOPAppenderWithDelay<E> extends AppenderBase<E> {
115 //
116 //        List<Long> longList;
117 //
118 //        NOPAppenderWithDelay(List<Long> longList) {
119 //            this.longList = new ArrayList<>(longList);
120 //        }
121 //
122 //        int i = 0;
123 //
124 //        @Override
125 //        protected void append(E eventObject) {
126 //            i++;
127 //            try {
128 //                writeLock.lock();
129 //                if ((i & 0xF) == 0) {
130 //                    delay(1);
131 //                } else {
132 //                    //longList.stream().map(x-> x+1);
133 //                }
134 //            } finally {
135 //                writeLock.unlock();
136 //            }
137 //
138 //        }
139 //
140 //    }
141 //
142 //    class ReconfiguringThread extends Thread {
143 //
144 //        AppenderAttachableImpl<String> aai;
145 //
146 //        ReconfiguringThread(AppenderAttachableImpl aai) {
147 //            this.aai = aai;
148 //        }
149 //
150 //        public void run() {
151 //            Thread.yield();
152 //            for (int i = 0; i < LOOP_LEN; i++) {
153 //                reconfigureWithDelay(aai);
154 //            }
155 //        }
156 //
157 //
158 //    }
159 //
160 //
161 //    class LoopingRunnable implements Runnable {
162 //
163 //        int num;
164 //        AppenderAttachableImpl<String> aai;
165 //        public boolean active = true;
166 //
167 //        LoopingRunnable(int num, AppenderAttachableImpl aai) {
168 //           this.num = num;
169 //           this.aai = aai;
170 //        }
171 //
172 //        public void run() {
173 //            System.out.println("LoopingRunnable.run.num="+num);
174 //            int i = 0;
175 //            while (active) {
176 //                if ((i & 0xFFFFF) == 0) {
177 //                    long id = Thread.currentThread().threadId();
178 //                    System.out.println("thread=" + id + " reconfigure=" + i);
179 //                }
180 //                aai.appendLoopOnAppenders(Integer.toString(i));
181 //                i++;
182 //                //Thread.yield();
183 //            }
184 //        }
185 //    }
186 
187 
188 }