I have an idea and it's kind of complicated and you must be familiar with assembly and multithreading to understand why I want to do this.
Did you ever notice that the cancel button never does anything when the program you are running is in a hot loop? But if you put an if statement in the hot loop you slow it down drastically.
In the Linux kernel, processes are scheduled by a timer onto the CPU by an interrupt when the timeslice has expired. See the schedule method in kernel/sched/core.c
Now in user space in Java and C programs, you have a thread in a hot loop unless you put an if statement inside the hot loop to check an aborted flag you cannot interrupt the hot loop from user space.
Only the kernel can preempt a thread.
But I have an idea on how we can preempt a thread in C programming from a userspace.
We can disassemble a function address to a RET to get its assembly. We can therefore identify the conditional jumps of the loop. We can introduce a go-to statement of __sched_yield() after the hot loop we can identify where in memory the relative address of the Sched yield from the disassembly.
From this, we can virtually interrupt a user thread from user space. Shall need to madvise/memprotect the executable code to update the conditional jump statement to jump to the goto statement.
What do you think? How easy is this?
How to learn the size of a function
How to disassemble a function with libopcodes
How to update memory of functions
In Java, C and Rust you can preempt a thread in a hot loop by directly changing the looped variable to go beyond the loop invariant. You can do this from any thread.
You can create cancellable APIs with this approach, your cancel token can represent all the loops indexes that the code is in. So you can create profoundly responsive code. Even if you are deep in encryption or compression or uploading data. As long as you're not in a syscall.
I also pasted a C version of this sourcecode below the Java version. The Rust version is below the C version
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
public class Scheduler {
public static class KernelThread extends Thread {
public Map<LightWeightThread, Boolean> scheduled = new HashMap<>();
public void preempt() {
for (LightWeightThread thread : scheduled.keySet()) {
scheduled.put(thread, false);
for (int loop = 0 ; loop < thread.getLoops(); loop++) {
thread.preempt(loop);
}
}
}
public void addLightWeightThread(LightWeightThread thread) {
scheduled.put(thread, false);
}
public boolean isScheduled(LightWeightThread lightWeightThread) {
return scheduled.get(lightWeightThread);
}
public void run() {
while (true) {
LightWeightThread previous = null;
for (LightWeightThread thread : scheduled.keySet()) {
scheduled.put(thread, false);
}
for (LightWeightThread thread : scheduled.keySet()) {
if (previous != null) {
scheduled.put(previous, false);
}
scheduled.put(thread, true);
thread.run();
previous = thread;
}
}
}
}
public interface Preemptible {
void registerLoop(int name, int defaultValue, int limit);
int increment(int name);
boolean isPreempted(int name);
int getLimit(int name);
int getValue(int name);
void preempt(int id);
int getLoops();
}
public static abstract class LightWeightThread implements Preemptible {
public int kernelThreadId;
public int threadId;
public KernelThread parent;
AtomicInteger[] values = new AtomicInteger[1];
int[] limits = new int[1];
boolean[] preempted = new boolean[1];
int[] remembered = new int[1];
public LightWeightThread(int kernelThreadId, int threadId, KernelThread parent) {
this.kernelThreadId = kernelThreadId;
this.threadId = threadId;
this.parent = parent;
for (int i = 0 ; i < values.length; i++) {
values[i] = new AtomicInteger();
}
}
public void run() {
}
public void registerLoop(int name, int defaultValue, int limit) {
if (preempted.length > name && remembered[name] < limit) {
values[name].set(remembered[name]);
limits[name] = limit;
} else {
values[name].set(defaultValue);
limits[name] = limit;
}
preempted[name] = false;
}
public int increment(int name) {
return values[name].incrementAndGet();
}
public boolean isPreempted(int name) {
return preempted[name];
}
public int getLimit(int name) {
return limits[name];
}
public int getValue(int name) {
return values[name].get();
}
public int initialVar(int name, int value) {
values[name].set(value);
return value;
}
public void preempt(int id) {
remembered[id] = values[id].get();
preempted[id] = true;
while (!values[id].compareAndSet(values[id].get(), limits[id])){};
}
public int getLoops() {
return values.length;
}
}
public static void main(String[] args) throws InterruptedException {
List<KernelThread> kernelThreads = new ArrayList<>();
for (int i = 0; i < 5; i++) {
KernelThread kt = new KernelThread();
for (int j = 0 ; j < 5; j++) {
LightWeightThread lightWeightThread = new LightWeightThread(i, j, kt) {
#Override
public void run() {
while (this.parent.isScheduled(this)) {
System.out.println(String.format("%d %d", this.kernelThreadId, this.threadId));
registerLoop(0, 0, 10000000);
for (initialVar(0, 0); getValue(0) < getLimit(0); increment(0)) {
Math.sqrt(getValue(0));
}
if (isPreempted(0)) {
System.out.println(String.format("%d %d: %d was preempted !%d < %d", this.kernelThreadId, this.threadId, 0, values[0].get(), limits[0]));
}
}
}
};
kt.addLightWeightThread(lightWeightThread);
}
kernelThreads.add(kt);
}
for (KernelThread kt : kernelThreads) {
kt.start();
}
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
for (KernelThread kt : kernelThreads) {
kt.preempt();
}
}
}, 10, 10);
for (KernelThread kt : kernelThreads) {
kt.join();
}
}
}
This is the C version of the same thing:
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
#include <time.h>
#include <math.h>
#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
struct lightweight_thread {
int thread_num;
volatile int preempted;
int num_loops;
int *limit;
volatile int *value;
int *remembered;
int kernel_thread_num;
struct lightweight_thread* (*user_function) (struct lightweight_thread*);
};
struct thread_info { /* Used as argument to thread_start() */
pthread_t thread_id; /* ID returned by pthread_create() */
int thread_num; /* Application-defined thread # */
char *argv_string; /* From command-line argument */
int lightweight_threads_num;
struct lightweight_thread *user_threads;
volatile int running;
};
struct timer_thread {
pthread_t thread_id;
struct thread_info *all_threads;
int num_threads;
int lightweight_threads_num;
int delay;
volatile int running;
};
static void *
timer_thread_start(void *arg) {
int iterations = 0;
struct timer_thread *timer_thread = arg;
int msec = 0, trigger = timer_thread->delay; /* 10ms */
clock_t before = clock();
while (timer_thread->running == 1 && iterations < 100000) {
do {
for (int i = 0 ; i < timer_thread->num_threads; i++) {
for (int j = 0 ; j < timer_thread->all_threads[i].lightweight_threads_num; j++) {
// printf("Preempting kernel thread %d user thread %d\n", i, j);
timer_thread->all_threads[i].user_threads[j].preempted = 0;
}
}
for (int i = 0 ; i < timer_thread->num_threads; i++) {
for (int j = 0 ; j < timer_thread->all_threads[i].lightweight_threads_num; j++) {
// printf("Preempting kernel thread %d user thread %d\n", i, j);
for (int loop = 0; loop < timer_thread->all_threads[i].user_threads[j].num_loops; loop++) {
timer_thread->all_threads[i].user_threads[j].remembered[loop] = timer_thread->all_threads[i].user_threads[j].value[loop];
timer_thread->all_threads[i].user_threads[j].value[loop] = timer_thread->all_threads[i].user_threads[j].limit[loop];
}
}
}
clock_t difference = clock() - before;
msec = difference * 1000 / CLOCKS_PER_SEC;
iterations++;
} while ( msec < trigger && iterations < 100000 );
// printf("Time taken %d seconds %d milliseconds (%d iterations)\n",
// msec/1000, msec%1000, iterations);
}
return 0;
}
/* Thread start function: display address near top of our stack,
and return upper-cased copy of argv_string. */
static void *
thread_start(void *arg)
{
struct thread_info *tinfo = arg;
char *uargv;
printf("Thread %d: top of stack near %p; argv_string=%s\n",
tinfo->thread_num, (void *) &tinfo, tinfo->argv_string);
uargv = strdup(tinfo->argv_string);
if (uargv == NULL)
handle_error("strdup");
for (char *p = uargv; *p != '\0'; p++) {
*p = toupper(*p);
}
while (tinfo->running == 1) {
for (int i = 0 ; i < tinfo->lightweight_threads_num; i++) {
tinfo->user_threads[i].preempted = 0;
}
int previous = -1;
for (int i = 0 ; i < tinfo->lightweight_threads_num; i++) {
if (previous != -1) {
tinfo->user_threads[previous].preempted = 0;
}
tinfo->user_threads[i].preempted = 1;
tinfo->user_threads[i].user_function(&tinfo->user_threads[i]);
previous = i;
}
}
return uargv;
}
void
register_loop(int index, int value, struct lightweight_thread* m, int limit) {
if (m->remembered[index] == -1) {
m->limit[index] = limit;
m->value[index] = value;
} else {
m->limit[index] = limit;
m->value[index] = m->remembered[index];
}
}
int
lightweight_thread_function(struct lightweight_thread* m)
{
while (m->preempted != 0) {
register_loop(0, 0, m, 100000000);
for (; m->value[0] < m->limit[0]; m->value[0]++) {
sqrt(m->value[0]);
}
printf("Kernel thread %d User thread %d ran\n", m->kernel_thread_num, m->thread_num);
}
return 0;
}
struct lightweight_thread*
create_lightweight_threads(int kernel_thread_num, int num_threads) {
struct lightweight_thread *lightweight_threads =
calloc(num_threads, sizeof(*lightweight_threads));
if (lightweight_threads == NULL)
handle_error("calloc lightweight threads");
for (int i = 0 ; i < num_threads ; i++) {
lightweight_threads[i].kernel_thread_num = kernel_thread_num;
lightweight_threads[i].thread_num = i;
lightweight_threads[i].num_loops = 1;
lightweight_threads[i].user_function = lightweight_thread_function;
int *remembered = calloc(lightweight_threads[i].num_loops, sizeof(*remembered));
int *value = calloc(lightweight_threads[i].num_loops, sizeof(*value));
int *limit = calloc(lightweight_threads[i].num_loops, sizeof(*limit));
lightweight_threads[i].remembered = remembered;
lightweight_threads[i].value = value;
lightweight_threads[i].limit = limit;
for (int j = 0 ; j < lightweight_threads[i].num_loops ; j++) {
lightweight_threads[i].remembered[j] = -1;
}
}
return lightweight_threads;
}
int
main(int argc, char *argv[])
{
int s, timer_s, opt, num_threads;
pthread_attr_t attr;
pthread_attr_t timer_attr;
ssize_t stack_size;
void *res;
int timer_result;
/* The "-s" option specifies a stack size for our threads. */
stack_size = 16384ul;
num_threads = 5;
while ((opt = getopt(argc, argv, "t:")) != -1) {
switch (opt) {
case 't':
num_threads = strtoul(optarg, NULL, 0);
break;
default:
fprintf(stderr, "Usage: %s [-t thread-size] arg...\n",
argv[0]);
exit(EXIT_FAILURE);
}
}
/* Initialize thread creation attributes. */
s = pthread_attr_init(&attr);
if (s != 0)
handle_error_en(s, "pthread_attr_init");
timer_s = pthread_attr_init(&timer_attr);
if (timer_s != 0)
handle_error_en(s, "pthread_attr_init timer_s");
if (stack_size > 0) {
s = pthread_attr_setstacksize(&attr, stack_size);
int t = pthread_attr_setstacksize(&timer_attr, stack_size);
if (t != 0)
handle_error_en(t, "pthread_attr_setstacksize timer");
if (s != 0)
handle_error_en(s, "pthread_attr_setstacksize");
}
/* Allocate memory for pthread_create() arguments. */
struct thread_info *tinfo = calloc(num_threads, sizeof(*tinfo));
if (tinfo == NULL)
handle_error("calloc");
for (int tnum = 0 ; tnum < num_threads; tnum++) {
tinfo[tnum].running = 1;
}
struct timer_thread *timer_info = calloc(1, sizeof(*timer_info));
timer_info->running = 1;
timer_info->delay = 10;
timer_info->num_threads = num_threads;
if (timer_info == NULL)
handle_error("calloc timer thread");
/* Create one thread for each command-line argument. */
timer_info->all_threads = tinfo;
for (int tnum = 0; tnum < num_threads; tnum++) {
tinfo[tnum].thread_num = tnum + 1;
tinfo[tnum].argv_string = argv[0];
struct lightweight_thread *lightweight_threads = create_lightweight_threads(tnum, num_threads);
tinfo[tnum].user_threads = lightweight_threads;
tinfo[tnum].lightweight_threads_num = num_threads;
/* The pthread_create() call stores the thread ID into
corresponding element of tinfo[]. */
s = pthread_create(&tinfo[tnum].thread_id, &attr,
&thread_start, &tinfo[tnum]);
if (s != 0)
handle_error_en(s, "pthread_create");
}
s = pthread_create(&timer_info[0].thread_id, &timer_attr,
&timer_thread_start, &timer_info[0]);
if (s != 0)
handle_error_en(s, "pthread_create");
/* Destroy the thread attributes object, since it is no
longer needed. */
s = pthread_attr_destroy(&attr);
if (s != 0)
handle_error_en(s, "pthread_attr_destroy");
s = pthread_attr_destroy(&timer_attr);
if (s != 0)
handle_error_en(s, "pthread_attr_destroy timer");
/* Now join with each thread, and display its returned value. */
s = pthread_join(timer_info->thread_id, &timer_result);
if (s != 0)
handle_error_en(s, "pthread_join");
printf("Joined timer thread");
for (int tnum = 0; tnum < num_threads; tnum++) {
tinfo[tnum].running = 0;
s = pthread_join(tinfo[tnum].thread_id, &res);
if (s != 0)
handle_error_en(s, "pthread_join");
printf("Joined with thread %d; returned value was %s\n",
tinfo[tnum].thread_num, (char *) res);
free(res); /* Free memory allocated by thread */
for (int user_thread_num = 0 ; user_thread_num < num_threads; user_thread_num++) {
free(tinfo[tnum].user_threads[user_thread_num].remembered);
free(tinfo[tnum].user_threads[user_thread_num].value);
free(tinfo[tnum].user_threads[user_thread_num].limit);
}
free(tinfo[tnum].user_threads);
}
free(timer_info);
free(tinfo);
exit(EXIT_SUCCESS);
}
The Rust version uses unsafe.
extern crate timer;
extern crate chrono;
use std::sync::Arc;
use std::thread;
use std::sync::atomic::{AtomicI32, Ordering};
use std::{time};
struct LightweightThread {
thread_num: i32,
preempted: AtomicI32,
num_loops: i32,
limit: Vec<AtomicI32>,
value: Vec<AtomicI32>,
remembered: Vec<AtomicI32>,
kernel_thread_num: i32,
lightweight_thread: fn(&mut LightweightThread)
}
fn register_loop(loopindex: usize, initialValue: i32, limit: i32, _thread: &mut LightweightThread) {
if _thread.remembered[loopindex].load(Ordering::Relaxed) < _thread.limit[loopindex].load(Ordering::Relaxed) {
_thread.value[loopindex].store( _thread.remembered[loopindex].load(Ordering::Relaxed), Ordering::Relaxed);
_thread.limit[loopindex].store(limit, Ordering::Relaxed);
} else {
_thread.value[loopindex].store(initialValue, Ordering::Relaxed);
_thread.limit[loopindex].store(limit, Ordering::Relaxed);
}
}
fn lightweight_thread(_thread: &mut LightweightThread) {
register_loop(0usize, 0, 1000000, _thread);
while _thread.preempted.load(Ordering::Relaxed) == 1 {
while _thread.value[0].load(Ordering::Relaxed) < _thread.limit[0].load(Ordering::Relaxed) {
let i = _thread.value[0].load(Ordering::Relaxed);
f64::sqrt(i.into());
_thread.value[0].fetch_add(1, Ordering::Relaxed);
}
}
println!("Kernel thread {} User thread {}", _thread.kernel_thread_num, _thread.thread_num)
}
fn main() {
println!("Hello, world!");
let timer = timer::Timer::new();
static mut threads:Vec<LightweightThread> = Vec::new();
let mut thread_handles = Vec::new();
for kernel_thread_num in 1..=5 {
let thread_join_handle = thread::spawn(move || {
for i in 1..=5 {
let mut lthread = LightweightThread {
thread_num: i,
preempted: AtomicI32::new(0),
num_loops: 1,
limit: Vec::new(),
value: Vec::new(),
remembered: Vec::new(),
kernel_thread_num: kernel_thread_num.clone(),
lightweight_thread: lightweight_thread
};
lthread.limit.push(AtomicI32::new(-1));
lthread.value.push(AtomicI32::new(-1));
lthread.remembered.push(AtomicI32::new(1));
unsafe {
threads.push(lthread);
}
}
loop {
let mut previous:Option<&mut LightweightThread> = None;
unsafe {
for (_pos, current_thread) in threads.iter_mut().enumerate() {
if current_thread.kernel_thread_num != kernel_thread_num {
continue;
}
if !previous.is_none() {
previous.unwrap().preempted.store(0, Ordering::Relaxed)
}
current_thread.preempted.store(1, Ordering::Relaxed);
(current_thread.lightweight_thread)(current_thread);
previous = Some(current_thread);
// println!("Running")
}
}
} // loop forever
}); // thread
thread_handles.push(thread_join_handle);
} // thread generation
let timer_handle = thread::spawn(move || {
unsafe {
loop {
for thread in threads.iter() {
thread.preempted.store(0, Ordering::Relaxed);
}
let mut previous:Option<usize> = None;
for (index, thread) in threads.iter_mut().enumerate() {
if !previous.is_none() {
threads[previous.unwrap()].preempted.store(0, Ordering::Relaxed);
}
previous = Some(index);
for loopindex in 0..thread.num_loops {
thread.remembered[loopindex as usize].store(thread.value[loopindex as usize].load(Ordering::Relaxed), Ordering::Relaxed);
thread.value[loopindex as usize].store(thread.limit[loopindex as usize].load(Ordering::Relaxed), Ordering::Relaxed);
}
thread.preempted.store(1, Ordering::Relaxed);
}
let ten_millis = time::Duration::from_millis(10);
thread::sleep(ten_millis);
} // loop
} // unsafe
}); // end of thread
timer_handle.join();
for thread in thread_handles {
thread.join();
}
}
I have a multi-level feedback class which I am not sure what its doing - it only ever seems to print the output I want when I run a pre-emptive multi-level class before it, when I don't it prints a different output. I am not sure how these are connected and making this happen.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MultiLevelFeedback {
List<Process> processList;
private int timeQuantum1;
private int timeQuantum2;
private int count;
int j=0;
private int ganntP[];
private int ganntT[];
private int totalWaitingTime = 0;
private int totalTurnAroundTime = 0;
private float avgWatingTime = 0;
private float avgTurnaroundTime = 0;
MultiLevelFeedback(List<Process> processList, int timeQuantum1,int timeQuantum2) {
count = processList.size();
ganntT=new int[200];
ganntP=new int[200];
this.timeQuantum1 = timeQuantum1;
this.timeQuantum2 = timeQuantum2;
this.processList=new ArrayList<Process>();
for(Process p : processList)
{
this.processList.add(new Process(p.getProcessId(), p.getArrivalTime(), p.getBurstTime(),p.getPriority()));
}
Collections.sort(this.processList, Process.BY_PRIORITY);
}
public void simulate() {
int currentTime =0;
int remainingProcess = count;
while (remainingProcess > processList.size()/2)
{
int clockTime=currentTime;
for (int i = 0; i < count; i++)
{
Process current = processList.get(i);
if(currentTime<current.getArrivalTime())
break;
if (current.getStartTime() == -1)
current.setStartTime(currentTime);
ganntP[j]=current.getProcessId();
ganntT[j]=currentTime;
j++;
if (current.getRemainingTime() <= timeQuantum1 && current.getEndTime()==-1)
{
current.setEndTime(currentTime + current.getRemainingTime());
currentTime += current.getRemainingTime();
current.setRemainingTime(0);
remainingProcess--;
}
else if (current.getRemainingTime()>timeQuantum1)
{
currentTime += timeQuantum1;
current.setRemainingTime(current.getRemainingTime()-timeQuantum1);
}
}
if(clockTime==currentTime)
{
currentTime++;
}
}
while (remainingProcess > processList.size()/2)
{
int clockTime=currentTime;
for (int i = 0; i < count; i++)
{
Process current = processList.get(i);
if(currentTime<current.getArrivalTime())
break;
if (current.getStartTime() == -1)
current.setStartTime(currentTime);
ganntP[j]=current.getProcessId();
ganntT[j]=currentTime;
j++;
if (current.getRemainingTime() <= timeQuantum2 && current.getEndTime()==-1)
{
current.setEndTime(currentTime + current.getRemainingTime());
currentTime += current.getRemainingTime();
current.setRemainingTime(0);
remainingProcess--;
}
else if (current.getRemainingTime()>timeQuantum2)
{
currentTime += timeQuantum2;
current.setRemainingTime(current.getRemainingTime()-timeQuantum2);
}
}
if(clockTime==currentTime)
{
currentTime++;
}
}
for(int i=0;i<count;i++)
{
Process current=processList.get(i);
if(current.getRemainingTime()>0 )
{
if(currentTime<current.getArrivalTime())
{
currentTime=current.getArrivalTime();
current.setStartTime(currentTime);
}
current.setEndTime(currentTime+current.getRemainingTime());
currentTime+=current.getRemainingTime();
}
}
for (int i = 0; i < count; i++)
{
Process current = processList.get(i);
current.setWaitingTime(current.getEndTime()-current.getBurstTime()-current.getArrivalTime());
current.setTurnaroundTime(current.getEndTime() - current.getArrivalTime());
totalWaitingTime += current.getWaitingTime();
totalTurnAroundTime += current.getTurnaroundTime();
}
avgWatingTime = (float) totalWaitingTime / count;
avgTurnaroundTime = (float) totalTurnAroundTime / count;
}
public void printResult()
{
System.out.println("Simulation result of MultiLevelFeedback ");
System.out.println("PId ArrivalT BurstT Priority StartT EndT WaitingT TurnAroundT");
for (Process p : processList)
{
System.out.println(p);
}
System.out.println("Average Waiting Time of MultiLevelFeedback "
+ avgWatingTime);
System.out.println("Average TurnAround Time of MultiLevelFeedback "
+ avgTurnaroundTime);
for(int i=0;i<j;i++)
{
System.out.println("time "+ganntT[i]+" process "+ganntP[i]);
}
System.out.println();
}
}
I am confused as there's nothing in the mlfq class which has anything to do with the pre-emptive multi-level class - they are both separate algorithms - except it is differing the output when I run both.
I decided to optimize the piece of code below but encounter with problem. I tried to change the ArrayList to thread-safe collection by using this discussion but unfortunately something went wrong. The code is compiling but throw the exception.
Exception in thread "main" java.lang.ClassCastException:
java.util.Collections$SynchronizedRandomAccessList cannot be cast to
java.util.ArrayList at
bfpasswrd_multi.PasswordCracker.doItMulti(PasswordCracker.java:73) at
bfpasswrd_multi.PasswordCracker.runMulti(PasswordCracker.java:60) at
bfpasswrd_multi.Test.main(Test.java:16)
Please, tell me what is wrong ?
package bfpasswrd_multi;
import java.util.Scanner;
public class Test
{
public static void main(String[] args)
{
System.out.print("Type password to be cracked: ");
#SuppressWarnings("resource")
String input = new Scanner(System.in).nextLine();
PasswordCracker cracker = new PasswordCracker();
System.out.println("Multithreaded");
cracker.runMulti(input);
cracker = new PasswordCracker();
System.out.println("Finished...");
}
}
package bfpasswrd_multi;
import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class PasswordCracker
{
String passwordToCrack;
public boolean passwordFound;
int min;
int max;
StringBuffer crackedPassword;
public void prepare(String text)
{
passwordToCrack = text;
passwordFound = false;
min = 48;
max = 57; // http://ascii.cl/
crackedPassword = new StringBuffer();
crackedPassword.append((char) (min - 1));
}
public void result()
{
System.out.println("Cracked Password is: " + crackedPassword.toString());
}
public void incrementString(StringBuffer toCrack, int min, int max)
{
toCrack.setCharAt(0, (char) ((int) toCrack.charAt(0) + 1));
for (int i = 0; i < toCrack.length(); i++)
{
if (toCrack.charAt(i) > (char) max)
{
toCrack.setCharAt(i, (char) min);
if (toCrack.length() == i + 1)
{
toCrack.append((char) min);
}
else
{
toCrack.setCharAt(i + 1, (char) ((int) toCrack.charAt(i + 1) + 1));
}
}
}
}
public void runMulti(String text)
{
prepare(text);
double time = System.nanoTime();
doItMulti();
time = System.nanoTime() - time;
System.out.println(time / (1000000000));
result();
}
public void doItMulti()
{
int cores = Runtime.getRuntime().availableProcessors();
ArrayList<Future<?>> tasks ; // How do I make my ArrayList Thread-Safe? Another approach to problem in Java?
// https://stackoverflow.com/questions/2444005/how-do-i-make-my-arraylist-thread-safe-another-approach-to-problem-in-java
tasks = (ArrayList<Future<?>>) Collections.synchronizedList(new ArrayList<Future<?>>(cores));
// ArrayList<Future<?>> tasks = new ArrayList<>(cores);
ExecutorService executor = Executors.newFixedThreadPool(cores);
final long step = 2000;
for (long i = 0; i < Long.MAX_VALUE; i += step)
{
while(tasks.size() > cores)
{
for(int w = 0; w < tasks.size();w++)
{
if(tasks.get(w).isDone())
{
tasks.remove(w);
break;
}
}
try
{
Thread.sleep(0);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
{
final long j = i;
if (passwordFound == false)
{
tasks.add(executor.submit(new Runnable()
{
public void run()
{
long border = j + step;
StringBuffer toCrack = new StringBuffer(10);
toCrack.append(constructString3(j, min, max));
for (long k = j; k < border; k++)
{
incrementString(toCrack, min, max);
boolean found = toCrack.toString().equals(passwordToCrack);
if (found)
{
crackedPassword = toCrack;
passwordFound = found;
break;
}
}
}
}));
}
else
{
break;
}
}
}
executor.shutdownNow();
}
public String constructString3(long number, long min, long max)
{
StringBuffer text = new StringBuffer();
if (number > Long.MAX_VALUE - min)
{
number = Long.MAX_VALUE - min;
}
ArrayList<Long> vector = new ArrayList<Long>(10);
vector.add(min - 1 + number);
long range = max - min + 1;
boolean nextLetter = false;
for (int i = 0; i < vector.size(); i++)
{
long nextLetterCounter = 0;
while (vector.get(i) > max)
{
nextLetter = true;
long multiplicator = Math.abs(vector.get(i) / range);
if ((vector.get(i) - (multiplicator * range)) < min)
{
multiplicator -= 1;
}
vector.set(i, vector.get(i) - (multiplicator * range));
nextLetterCounter += multiplicator;
}
if (nextLetter)
{
vector.add((long) (min + nextLetterCounter - 1));
nextLetter = false;
}
text.append((char) vector.get(i).intValue());
}
return text.toString();
}
}
Many thanks in advance !
The issue that you're seeing is with this line:
tasks = (ArrayList<Future<?>>) Collections.synchronizedList(new ArrayList<Future<?>>(cores));
Collections.synchronizedList doesn't return an ArrayList; it returns some subclass of List - java.util.Collections$SynchronizedRandomAccessList to be exact - and I don't know anything about that class other than it's a List, but it's not an ArrayList.
The easy solution to this is to declare tasks to be a List<Future<?>>:
List<Future<?>> tasks =
Collections.synchronizedList(new ArrayList<Future<?>>(cores));
Dear community members thanks you for your comments. It seems that now my safe-thread list is working. For the people who interesting in solution I will submit the resolved code below. Also, probably I should mention that I rename task
to futures, please pay attention. Once again everybody thanks !
package bfpasswrd_multi;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class PasswordCracker
{
String passwordToCrack;
public boolean passwordFound;
int min;
int max;
StringBuffer crackedPassword;
public void prepare(String text)
{
passwordToCrack = text;
passwordFound = false;
min = 48;
max = 57; // http://ascii.cl/
crackedPassword = new StringBuffer();
crackedPassword.append((char) (min - 1));
}
public void result()
{
System.out.println("Cracked Password is: " + crackedPassword.toString());
}
public void incrementString(StringBuffer toCrack, int min, int max)
{
toCrack.setCharAt(0, (char) ((int) toCrack.charAt(0) + 1));
for (int i = 0; i < toCrack.length(); i++)
{
if (toCrack.charAt(i) > (char) max)
{
toCrack.setCharAt(i, (char) min);
if (toCrack.length() == i + 1)
{
toCrack.append((char) min);
}
else
{
toCrack.setCharAt(i + 1, (char) ((int) toCrack.charAt(i + 1) + 1));
}
}
}
}
public void runMulti(String text)
{
prepare(text);
double time = System.nanoTime();
doItMulti();
time = System.nanoTime() - time;
System.out.println(time / (1000000000));
result();
}
public void doItMulti()
{
int cores = Runtime.getRuntime().availableProcessors();
// ArrayList<Future<?>> task; // HOW IT WAS
//
// tasks = (ArrayList<Future<?>>) Collections.synchronizedList(new ArrayList<Future<?>>(cores)); // HOW IT WAS
List<Future<?>> futures ; // THE SOLUTION
futures = Collections.synchronizedList(new ArrayList<Future<?>>(cores)); // THE SOLUTION
// ArrayList<Future<?>> tasks = new ArrayList<>(cores);
ExecutorService executor = Executors.newFixedThreadPool(cores);
final long step = 2000;
for (long i = 0; i < Long.MAX_VALUE; i += step)
{
while(futures.size() > cores)
{
for(int w = 0; w < futures.size();w++)
{
if(futures.get(w).isDone())
{
futures.remove(w);
break;
}
}
try
{
Thread.sleep(0);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
{
final long j = i;
if (passwordFound == false)
{
futures.add(executor.submit(new Runnable()
{
public void run()
{
long border = j + step;
StringBuffer toCrack = new StringBuffer(10);
toCrack.append(constructString3(j, min, max));
for (long k = j; k < border; k++)
{
incrementString(toCrack, min, max);
boolean found = toCrack.toString().equals(passwordToCrack);
if (found)
{
crackedPassword = toCrack;
passwordFound = found;
break;
}
}
}
}));
}
else
{
break;
}
}
}
executor.shutdownNow();
}
public String constructString3(long number, long min, long max)
{
StringBuffer text = new StringBuffer();
if (number > Long.MAX_VALUE - min)
{
number = Long.MAX_VALUE - min;
}
ArrayList<Long> vector = new ArrayList<Long>(10);
vector.add(min - 1 + number);
long range = max - min + 1;
boolean nextLetter = false;
for (int i = 0; i < vector.size(); i++)
{
long nextLetterCounter = 0;
while (vector.get(i) > max)
{
nextLetter = true;
long multiplicator = Math.abs(vector.get(i) / range);
if ((vector.get(i) - (multiplicator * range)) < min)
{
multiplicator -= 1;
}
vector.set(i, vector.get(i) - (multiplicator * range));
nextLetterCounter += multiplicator;
}
if (nextLetter)
{
vector.add((long) (min + nextLetterCounter - 1));
nextLetter = false;
}
text.append((char) vector.get(i).intValue());
}
return text.toString();
}
}
public class RandomPrime
{
public static void main(String[] args)
{
int squareNumber = readInput();
BigInteger randomPrimes[] = generateRandomPrime(squareNumber);
}
public static BigInteger[] generateRandomPrime(int num)
{
int numberOfPrimes = (int) Math.sqrt(num);
int start, end, step;
start = 1;
step = num / numberOfPrimes;
end = start + (step - 1);
/*int randomPrimes[] = new int[numberOfPrimes];*/
BigInteger randomPrimes[] = new BigInteger[numberOfPrimes];
Random rand = new Random();
int tempPrime;
for (int i = 0; i < numberOfPrimes; i++) {
while (true) {
tempPrime = rand.nextInt(end - start) + start;
if (isPrime(tempPrime)) {
randomPrimes[i] = new BigInteger(tempPrime + "");
System.out.println("Random prime is "+tempPrime);
break;
}
}
start = end + 1;
end = end + (step - 1);
System.out.println("OUTER WHILE");
}
return randomPrimes;
}
public static boolean isPrime(int num)
{
for (int i = 2; i < num; i++) {
if (num % i == 0) {
return false;
}
}
return true;
}
public static int readInput()
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int num = 0, sqrt;
while (true) {
System.out.println("Enter a square number");
try {
num = Integer.parseInt(br.readLine());
sqrt = (int) Math.sqrt(num);
if (num == (sqrt * sqrt)) {
System.out.println("Entered valid square num is "+num);
break;
}
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Entered a non square number.So");
}
return num;
}
}
This is the code I wrote. I want to generate uniformly distributed random prime. This code works.
My problem: I am not sure whether my code generated uniformly distributed primes. Is it correct? If not, how do I solve it?
I need to implement a "round-robin" scheduler with a job class that I cannot modify. Round-robin scheduler should process the job that has been waiting the longest first, then reset timer to zero. If two jobs have same wait time, lower id is processed first. The job class only gives three values (job id, remaining duration, and priority(which is not needed for this). each job has a start time, so only a couple of jobs may be available during first cycle, few more next cycle, etc. Since the "job array" I am calling is different every time I call it, I'm not sure how to store the wait times.
This is the job class:
public class Jobs{
private int[] stas = new int[0];
private int[] durs = new int[0];
private int[] lefs = new int[0];
private int[] pris = new int[0];
private int[] fins = new int[0];
private int clock;
public Jobs()
{
this("joblist.csv");
}
public Jobs(String filename)
{
BufferedReader fp = null;
String line = "";
String[] b = null;
int[] tmp;
try
{
fp = new BufferedReader(new FileReader(filename));
while((line = fp.readLine()) != null)
{
b = line.split(",");
if(b.length == 3)
{
try
{
int sta = Integer.parseInt(b[0]);
//System.out.println("sta: " + b[0]);
int dur = Integer.parseInt(b[1]);
//System.out.println("dur: " + b[1]);
int pri = Integer.parseInt(b[2]);
//System.out.println("pri: " + b[2]);
stas = app(stas, sta);
//System.out.println("stas: " + Arrays.toString(stas));
durs = app(durs, dur);
//System.out.println("durs: " + Arrays.toString(durs));
lefs = app(lefs, dur);
//System.out.println("lefs: " + Arrays.toString(lefs));
pris = app(pris, pri);
//System.out.println("pris: " + Arrays.toString(pris));
fins = app(fins, -1);
//System.out.println("fins: " + Arrays.toString(fins));
}
catch(NumberFormatException e) {}
}
}
fp.close();
}
catch(FileNotFoundException e) { e.printStackTrace(); }
catch(IOException e) { e.printStackTrace(); }
clock = 0;
}
public boolean done()
{
boolean done = true;
for(int i=0; done && i<lefs.length; i++)
if(lefs[i]>0) done=false;
return done;
}
public int getClock() { return clock; }
public int[][] getJobs()
{
int count = 0;
for(int i=0; i<stas.length; i++)
if(stas[i]<=clock && lefs[i]>0)
count++;
int[][] jobs = new int[count][3];
count = 0;
for(int i=0; i<stas.length; i++)
if(stas[i]<=clock && lefs[i]>0)
{
jobs[count] = new int[]{i, lefs[i], pris[i]};
count++;
}
return jobs;
}
public int cycle() { return cycle(-1); }
public int cycle(int j)
{
if(j>=0 && j<lefs.length && clock>=stas[j] && lefs[j]>0)
{
lefs[j]--;
if(lefs[j] == 0) fins[j] = clock+1;
}
clock++;
return clock;
}
private int[] app(int[] a, int b)
{
int[] tmp = new int[a.length+1];
for(int i=0; i<a.length; i++) tmp[i] = a[i];
tmp[a.length] = b;
return tmp;
}
public String report()
{
String r = "JOB,PRIORITY,START,DURATION,FINISH,DELAY,PRI*DELAY\n";
float dn=0;
float pdn=0;
for(int i=0; i<stas.length; i++)
{
if(fins[i]>=0)
{
int delay = ((fins[i]-stas[i])-durs[i]);
r+= ""+i+","+pris[i]+","+stas[i]+","+durs[i]+","+fins[i]+","+delay+","+(pris[i]*delay)+"\n";
dn+= delay;
pdn+= pris[i]*delay;
}
else
{
int delay = ((clock*10-stas[i])-durs[i]);
r+= ""+i+","+pris[i]+","+stas[i]+","+durs[i]+","+fins[i]+","+delay+","+(pris[i]*delay)+"\n";
dn+= delay;
pdn+= pris[i]*delay;
}
}
if(stas.length>0)
{
r+= "Avg,,,,,"+(dn/stas.length)+","+pdn/stas.length+"\n";
}
return r;
}
public String toString()
{
String r = "There are "+stas.length+" jobs:\n";
for(int i=0; i<stas.length; i++)
{
r+= " JOB "+i+": START="+stas[i]+" DURATION="+durs[i]+" DURATION_LEFT="+lefs[i]+" PRIORITY="+pris[i]+"\n";
}
return r;
}
I don't need full code, just an idea of how to store wait times and cycle the correct job.
While a array based solution 'may' work, I would advocate a more object oriented approach. Create 'Job' class with the desire attributes (id, start_time, wait etc). Using the csv file, create Job objects and hold them in a list. Write a comparator to sort this jobs-list (in this case based on job wait/age would be the factor).
The job executor then has to do the following:
while(jobs exist) {
iterate on the list {
if job is executable // start_time > current sys_time
consume cycles/job for executable jobs
mark completed jobs (optional)
}
remove the completed jobs
}
//\ This loop will add +1 to each job
for(int i = 0; i < jobs.length; i++)
{
waitTime[jobs[i][0]] += 1;
}
int longestWait = 0;//\ This holds value for greatest wait time
int nextJob = 0; //\ This holds value for index of job with greatest wait time
//\ this loop will check for the greatest wait time and and set variables accordingly
for(int i = 0; i < waitTime.length; i++)
{
if(waitTime[i] > longestWait)
{
longestWait = waitTime[i];
nextJob = i;
}
}
//\ this cycles the job with the highest wait time
jobsource.cycle(nextJob);
//\ this resets the wait time for processed job
waitTime[nextJob] = 0;