// File: flastest[P]HeterogeneousParallelDijkstra/BGL_Dijkstra.cc
// Function: parallel_dijkstra(boost::adjacency_list<boost::listS, boost::vecS, boost::directedS, boost::no_property, boost::property<boost::edge_weight_t, int, boost::no_property>, boost::no_property, boost::listS> const&, unsigned long const&, std::map<unsigned long, unsigned long, std::less<unsigned long>, std::allocator<std::pair<unsigned long const, unsigned long>>>&, int)
distance_map_t parallel_dijkstra(const graph_t &graph, 
						const vertex_descriptor &source, 
						predecessor_map_t &predecessors,
						int NUM_THREADS)
{

	debug_file_stream.open("debuglog"+std::to_string(NUM_THREADS)+".txt");
	//all the threads, pretty self explanatory
	vector<thread> threads;

	mutex_map_t distance_mutexes;

	//I need a new pqueue for all the offers.
	offer_pqueue_t offer_pq;

	//let's the mutex list for the predecessors
	mutex_map_t predecessor_mutexes;

	//this keeps track of the threads that are done
	vector<bool> done(NUM_THREADS, false); 

	distance_map_t distances = initialize_distances_from_source_and_mutex_maps(graph, distance_mutexes, predecessor_mutexes);


	//for using BGL's graph_t (adjacency table):
	//https://www.boost.org/doc/libs/1_60_0/libs/graph/doc/adjacency_list.html

	//set the source node's distance from source to zero
	distances[source] = 0;

	const auto weight = get(edge_weight, graph);

	//now to enqueue source's neighbors in the pqueue
	offer_pq.push(offer_t(source,0.0f));
	auto [start, finish] = out_edges(source,graph);
	for(;start != finish; start++)
	{
		if (DEBUG) std::cout << "adding an offer from source to "<<target(*start,graph)<<" of distance "<<get(weight, *start)<<std::endl;
		offer_t offer(target(*start,graph),get(weight, *start));
		offer_pq.push(offer);
	}


	//ok now all the threads gotta do their things. 
	for (int thread_id = 0; thread_id < NUM_THREADS;)
	{
		threads.push_back(
			std::thread([&, thread_id](){
				parallel_dijkstra_thread(
					done,
					thread_id,
					offer_pq,
					distances,
					distance_mutexes,
					predecessor_mutexes,
					predecessors,
					graph);}));
		thread_id++;
	}

	//join threads!
	for(int thread = 0; thread < NUM_THREADS; thread++)
	{
		threads[thread].join();
	}
	debug_file_stream.close();
	return distances;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x310, %rsp            # imm = 0x310
movq %rdi, -0x2a0(%rbp)
movq %rdi, %rax
movq %rax, -0x298(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movl %r8d, -0x24(%rbp)
movl -0x24(%rbp), %esi
leaq -0x88(%rbp), %rdi
movq %rdi, -0x290(%rbp)
callq 0xabb0
movq -0x290(%rbp), %rdx
leaq 0xdc96(%rip), %rsi      # 0x2ab7a
leaq -0x68(%rbp), %rdi
callq 0x1e070
jmp 0x1ceef
leaq 0xdc8d(%rip), %rdx      # 0x2ab83
leaq -0x48(%rbp), %rdi
leaq -0x68(%rbp), %rsi
callq 0xaa10
jmp 0x1cf05
leaq 0x21464(%rip), %rdi     # 0x3e370
leaq -0x48(%rbp), %rsi
movl $0x10, %edx
callq 0x4180
jmp 0x1cf1c
leaq -0x48(%rbp), %rdi
callq 0x41e0
leaq -0x68(%rbp), %rdi
callq 0x41e0
leaq -0x88(%rbp), %rdi
callq 0x41e0
leaq -0xb0(%rbp), %rdi
callq 0x1e5c0
leaq -0xe0(%rbp), %rdi
callq 0x1e5e0
leaq -0x100(%rbp), %rdi
callq 0x1e600
jmp 0x1cf60
leaq -0x130(%rbp), %rdi
callq 0x1e5e0
movslq -0x24(%rbp), %rax
movq %rax, -0x2b0(%rbp)
movb $0x0, -0x159(%rbp)
leaq -0x15a(%rbp), %rdi
movq %rdi, -0x2a8(%rbp)
callq 0x1e630
movq -0x2b0(%rbp), %rsi
movq -0x2a8(%rbp), %rcx
leaq -0x158(%rbp), %rdi
leaq -0x159(%rbp), %rdx
callq 0x1e650
jmp 0x1cfb4
leaq -0x15a(%rbp), %rdi
callq 0x1e6d0
movq -0x2a0(%rbp), %rdi
movb $0x0, -0x15b(%rbp)
movq -0x10(%rbp), %rsi
leaq -0xe0(%rbp), %rdx
leaq -0x130(%rbp), %rcx
callq 0x1b920
jmp 0x1cfe7
movq -0x2a0(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x1da20
movq %rax, -0x2b8(%rbp)
jmp 0x1d000
movq -0x2b8(%rbp), %rax
movl $0x0, (%rax)
movq -0x10(%rbp), %rsi
xorl %edi, %edi
callq 0x15570
movl %eax, -0x2bc(%rbp)
jmp 0x1d020
movl -0x2bc(%rbp), %eax
movl %eax, -0x160(%rbp)
movq -0x18(%rbp), %rsi
movl $0x0, -0x174(%rbp)
leaq -0x170(%rbp), %rdi
leaq -0x174(%rbp), %rdx
callq 0x1e6f0
jmp 0x1d04f
leaq -0x100(%rbp), %rdi
leaq -0x170(%rbp), %rsi
callq 0x1e1f0
jmp 0x1d064
movq -0x18(%rbp), %rax
movq (%rax), %rsi
movq -0x10(%rbp), %rdx
leaq -0x198(%rbp), %rdi
callq 0x12390
jmp 0x1d07d
leaq -0x198(%rbp), %rdi
callq 0x1dc20
movq %rax, -0x1a0(%rbp)
leaq -0x198(%rbp), %rdi
callq 0x1dc40
movq %rax, -0x1a8(%rbp)
movq -0x1a0(%rbp), %rdi
movq -0x1a8(%rbp), %rsi
callq 0x124b0
movb %al, -0x2bd(%rbp)
jmp 0x1d0be
movb -0x2bd(%rbp), %al
testb $0x1, %al
jne 0x1d0cd
jmp 0x1d369
testb $0x1, 0x2126d(%rip)     # 0x3e341
je 0x1d28a
movq 0x20ee7(%rip), %rdi     # 0x3dfc8
leaq 0xdaa0(%rip), %rsi      # 0x2ab88
callq 0x4310
movq %rax, -0x2c8(%rbp)
jmp 0x1d0f6
movq -0x1a0(%rbp), %rsi
leaq -0x1c0(%rbp), %rdi
callq 0x12510
jmp 0x1d10b
movq -0x10(%rbp), %rsi
leaq -0x1c0(%rbp), %rdi
callq 0x124f0
movq %rax, -0x2d0(%rbp)
jmp 0x1d124
movq -0x2d0(%rbp), %rsi
movq -0x2c8(%rbp), %rdi
callq 0x40b0
movq %rax, -0x2d8(%rbp)
jmp 0x1d140
movq -0x2d8(%rbp), %rdi
leaq 0xda5a(%rip), %rsi      # 0x2aba8
callq 0x4310
movq %rax, -0x2e0(%rbp)
jmp 0x1d15c
movq -0x1a0(%rbp), %rsi
leaq -0x1d8(%rbp), %rdi
callq 0x12510
jmp 0x1d171
leaq -0x160(%rbp), %rdi
leaq -0x1d8(%rbp), %rsi
callq 0x13f50
movq %rax, -0x2e8(%rbp)
jmp 0x1d18d
movq -0x2e0(%rbp), %rdi
movq -0x2e8(%rbp), %rax
movl (%rax), %esi
callq 0x4510
movq %rax, -0x2f0(%rbp)
jmp 0x1d1ab
movq -0x2f0(%rbp), %rdi
movq 0x20ddf(%rip), %rsi     # 0x3df98
callq 0x4370
jmp 0x1d1c0
jmp 0x1d28a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x1d211
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x1d208
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0x48(%rbp), %rdi
callq 0x41e0
leaq -0x68(%rbp), %rdi
callq 0x41e0
leaq -0x88(%rbp), %rdi
callq 0x41e0
jmp 0x1d55a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x1d542
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0x15a(%rbp), %rdi
callq 0x1e6d0
jmp 0x1d52a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x1d51e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x1d512
movq -0x1a0(%rbp), %rsi
leaq -0x208(%rbp), %rdi
callq 0x12510
jmp 0x1d29f
movq -0x10(%rbp), %rsi
leaq -0x208(%rbp), %rdi
callq 0x124f0
movq %rax, -0x2f8(%rbp)
jmp 0x1d2b8
movq -0x2f8(%rbp), %rax
movq %rax, -0x1f0(%rbp)
movq -0x1a0(%rbp), %rsi
leaq -0x220(%rbp), %rdi
callq 0x12510
jmp 0x1d2db
leaq -0x160(%rbp), %rdi
leaq -0x220(%rbp), %rsi
callq 0x13f50
movq %rax, -0x300(%rbp)
jmp 0x1d2f7
movq -0x300(%rbp), %rdx
leaq -0x1e8(%rbp), %rdi
leaq -0x1f0(%rbp), %rsi
callq 0x1e720
jmp 0x1d313
leaq -0x100(%rbp), %rdi
leaq -0x1e8(%rbp), %rsi
callq 0x1e750
jmp 0x1d328
jmp 0x1d32a
movq -0x1a0(%rbp), %rdi
xorl %esi, %esi
callq 0x1dcd0
movq %rdx, -0x310(%rbp)
movq %rax, -0x308(%rbp)
jmp 0x1d348
movq -0x310(%rbp), %rax
movq -0x308(%rbp), %rcx
movq %rcx, -0x230(%rbp)
movq %rax, -0x228(%rbp)
jmp 0x1d0a3
movl $0x0, -0x234(%rbp)
movl -0x234(%rbp), %eax
cmpl -0x24(%rbp), %eax
jge 0x1d457
movq -0x2a0(%rbp), %rax
movl -0x234(%rbp), %ecx
movl %ecx, -0x280(%rbp)
leaq -0x158(%rbp), %rcx
movq %rcx, -0x278(%rbp)
leaq -0x100(%rbp), %rcx
movq %rcx, -0x270(%rbp)
movq %rax, -0x268(%rbp)
leaq -0xe0(%rbp), %rax
movq %rax, -0x260(%rbp)
leaq -0x130(%rbp), %rax
movq %rax, -0x258(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x250(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x248(%rbp)
leaq -0x240(%rbp), %rdi
leaq -0x280(%rbp), %rsi
callq 0x1d570
jmp 0x1d3ff
leaq -0xb0(%rbp), %rdi
leaq -0x240(%rbp), %rsi
callq 0x1e7a0
jmp 0x1d414
leaq -0x240(%rbp), %rdi
callq 0x1e7d0
movl -0x234(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x234(%rbp)
jmp 0x1d373
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0x240(%rbp), %rdi
callq 0x1e7d0
jmp 0x1d512
movl $0x0, -0x284(%rbp)
movl -0x284(%rbp), %eax
cmpl -0x24(%rbp), %eax
jge 0x1d49c
movslq -0x284(%rbp), %rsi
leaq -0xb0(%rbp), %rdi
callq 0x1e800
movq %rax, %rdi
callq 0x44f0
jmp 0x1d489
jmp 0x1d48b
movl -0x284(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x284(%rbp)
jmp 0x1d461
leaq 0x20ecd(%rip), %rdi     # 0x3e370
callq 0x4430
jmp 0x1d4aa
movb $0x1, -0x15b(%rbp)
testb $0x1, -0x15b(%rbp)
jne 0x1d4c6
movq -0x2a0(%rbp), %rdi
callq 0xb400
leaq -0x158(%rbp), %rdi
callq 0x1e820
leaq -0x130(%rbp), %rdi
callq 0x1e4d0
leaq -0x100(%rbp), %rdi
callq 0x1e840
leaq -0xe0(%rbp), %rdi
callq 0x1e4d0
leaq -0xb0(%rbp), %rdi
callq 0x1e860
movq -0x298(%rbp), %rax
addq $0x310, %rsp            # imm = 0x310
popq %rbp
retq
movq -0x2a0(%rbp), %rdi
callq 0xb400
leaq -0x158(%rbp), %rdi
callq 0x1e820
leaq -0x130(%rbp), %rdi
callq 0x1e4d0
leaq -0x100(%rbp), %rdi
callq 0x1e840
leaq -0xe0(%rbp), %rdi
callq 0x1e4d0
leaq -0xb0(%rbp), %rdi
callq 0x1e860
movq -0x90(%rbp), %rdi
callq 0x4520
nopw %cs:(%rax,%rax)