Paste number 86549: Prime Sieve with libdispatch

Index of paste annotations: 1 | 2 | 3 | 4 | 5 | 6 | 7

Paste number 86549: Prime Sieve with libdispatch
Pasted by: David Leimbach
When:2 years, 8 months ago
Share:Tweet this! | http://paste.lisp.org/+1US5
Channel:None
Paste contents:
Raw Source | XML | Display As
// David Leimbach
// September 4, 2009
//
// First, unclean attempt at a prime number sieve in C with libdispatch
//
// Special thanks to Kevin Van Vechten and Jordan Hubbard for guidance through this new API!
//
// Thanks to Apple for making Snow Leopard so affordable!

#include <dispatch/dispatch.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>

#define MAX 300

struct context
{
  int mynum;
  int has_spawned;
  int writefd;
};

void setup_block(int read_fd) {
  dispatch_source_t piperead;
  struct context * ctx;
  piperead = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, read_fd,
				    0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0));

  ctx = calloc(sizeof(struct context), 1);

  ctx->has_spawned = 0;

  dispatch_source_set_event_handler(piperead, 
				    ^{
				      int val;
				      int fd[2];
				      struct context * ctx = dispatch_get_context(piperead);

				      read(read_fd, &val, 4);

				      if (ctx->has_spawned == 0) {
					pipe(fd);
					ctx->writefd = fd[1];
					ctx->mynum = val;
					ctx->has_spawned = 1;
					setup_block(fd[0]);
					printf("%d\n", val);
				      }
				      else {
					if (val % ctx->mynum != 0) {
					  write(ctx->writefd, &val, 4);
					}
				      }
				    });
  
  dispatch_set_context(piperead, ctx);  // associate this state with this context
				    
  dispatch_resume(piperead);
}


void run_sieve(int writefd) {
  int x;
  
  for(x=2; x <= MAX; ++x)
    write(writefd, &x, 4);

  sleep(2);
}

int main () {
  int fd[2];

  pipe(fd);

  setup_block(fd[0]);

  run_sieve(fd[1]);

  return 0;
}

Annotations for this paste:

Annotation number 1: lost the sleep, using real synchronization now.
Pasted by: David Leimbach
When:2 years, 8 months ago
Share:Tweet this! | http://paste.lisp.org/+1US5/1
Paste contents:
Raw Source | Display As
// David Leimbach
// September 4, 2009
//
// First, unclean attempt at a prime number sieve in C with libdispatch
//
// Special thanks to Kevin Van Vechten and Jordan Hubbard for guidance through this new API!
//
// Thanks to Apple for making Snow Leopard so affordable!

#include <dispatch/dispatch.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>

#define MAX 1000
#define LAST -1

struct context
{
  int mynum;
  int has_spawned;
  int writefd;
};

struct {
  dispatch_queue_t q;
  int count;
  dispatch_semaphore_t sync;
} proc_sync;

void increment_proc_count() {
  dispatch_sync(proc_sync.q, 
		^{
		  proc_sync.count++;
		});
}

void decrement_proc_count() {
  dispatch_sync(proc_sync.q, 
		^{
		  if (proc_sync.count - 1 == 0) {
		    dispatch_semaphore_signal(proc_sync.sync);
		    fflush(stdout);
		  }
		  proc_sync.count--;
		});
}
	

void cleanup_proc(void * p) {
  struct context * ctx = p;
  close(ctx->writefd);
  free(p);
  decrement_proc_count();
}

void setup_block(int read_fd) {
  dispatch_source_t piperead;
  struct context * ctx;
  piperead = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, read_fd,
				    0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0));

  ctx = calloc(sizeof(struct context), 1);

  ctx->has_spawned = 0;

  dispatch_source_set_event_handler(piperead, 
				    ^{
				      int val;
				      int fd[2];
				      struct context * ctx = dispatch_get_context(piperead);

				      read(read_fd, &val, 4);
				      
				      if (val != LAST) {
					if (ctx->has_spawned == 0) {
					  pipe(fd);
					  ctx->writefd = fd[1];
					  ctx->mynum = val;
					  ctx->has_spawned = 1;
					  setup_block(fd[0]);
					  printf("%d\n", val);
					}
					else {
					  if (val % ctx->mynum != 0) {
					    write(ctx->writefd, &val, 4);
					  }
					}
				      }
				      else {
					write(ctx->writefd, &val, 4);
					close(read_fd);
					dispatch_release(piperead);
				      }
				    });
  
  dispatch_set_context(piperead, ctx);  // associate this state with this context

  dispatch_set_finalizer_f(piperead, cleanup_proc);

  increment_proc_count();
  
  dispatch_resume(piperead);
}


void run_sieve(int writefd) {
  int x;
  
  for(x=2; x <= MAX; ++x) {
    write(writefd, &x, 4);
  }
  //  sleep(10);
  x = LAST;
  write(writefd, &x, 4);
}

int main () {
  int fd[2];

  // build up a global tracker of "processes" (contexts)
  proc_sync.count = 0;
  proc_sync.sync = dispatch_semaphore_create(0);
  proc_sync.q = dispatch_queue_create("sync", NULL);

  // Post an asynchronous block that waits on the process signal
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), 
		 ^{
		   dispatch_semaphore_wait(proc_sync.sync, DISPATCH_TIME_FOREVER);
		   exit(0);
		 });

  // Our blocks are dispatched based on pipe FDs.
  pipe(fd);

  setup_block(fd[0]);

  // Run the sieve proc
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{run_sieve(fd[1]);});
  
  // wait for all outstanding blocks on queues
  dispatch_main();
  return 0;
}

Annotation number 2: check the pipes...
Pasted by: Dave Leimbach
When:2 years, 8 months ago
Share:Tweet this! | http://paste.lisp.org/+1US5/2
Paste contents:
Raw Source | Display As
// David Leimbach
// September 4, 2009
//
// First, unclean attempt at a prime number sieve in C with libdispatch
//
// Special thanks to Kevin Van Vechten and Jordan Hubbard for guidance through this new API!
//
// Thanks to Apple for making Snow Leopard so affordable!

#include <dispatch/dispatch.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>

#if !defined(MAX)
#define MAX 700
#endif

#define LAST -1

struct context
{
  int mynum;
  int has_spawned;
  int writefd;
};

struct {
  dispatch_queue_t q;
  int count;
  dispatch_semaphore_t sync;
} proc_sync;

void increment_proc_count() {
  dispatch_sync(proc_sync.q, 
		^{
		  proc_sync.count++;
		});
}

void decrement_proc_count() {
  dispatch_sync(proc_sync.q, 
		^{
		  if (proc_sync.count - 1 == 0) {
		    dispatch_semaphore_signal(proc_sync.sync);
		    fflush(stdout);
		  }
		  proc_sync.count--;
		});
}
	

void cleanup_proc(void * p) {
  struct context * ctx = p;
  close(ctx->writefd);
  free(p);
  decrement_proc_count();
}

void setup_block(int read_fd) {
  dispatch_source_t piperead;
  struct context * ctx;
  piperead = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, read_fd,
				    0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0));

  ctx = calloc(sizeof(struct context), 1);

  ctx->has_spawned = 0;

  dispatch_source_set_event_handler(piperead, 
				    ^{
				      int val;
				      int fd[2];
				      struct context * ctx = dispatch_get_context(piperead);

				      read(read_fd, &val, 4);
				      
				      if (val != LAST) {
					if (ctx->has_spawned == 0) {
					  if (pipe(fd) != 0) {
					    perror("Please increase your ulimit for file descriptors\naborting...\n");
					    abort();
					  }
					  ctx->writefd = fd[1];
					  ctx->mynum = val;
					  ctx->has_spawned = 1;
					  setup_block(fd[0]);
					  printf("%d\n", val);
					}
					else {
					  if (val % ctx->mynum != 0) {
					    write(ctx->writefd, &val, 4);
					  }
					}
				      }
				      else {
					write(ctx->writefd, &val, 4);
					close(read_fd);
					dispatch_release(piperead);
				      }
				    });
  
  dispatch_set_context(piperead, ctx);  // associate this state with this context

  dispatch_set_finalizer_f(piperead, cleanup_proc);

  increment_proc_count();
  
  dispatch_resume(piperead);
}


void run_sieve(int writefd) {
  int x;
  
  for(x=2; x <= MAX; ++x) {
    write(writefd, &x, 4);
  }
  //  sleep(10);
  x = LAST;
  write(writefd, &x, 4);
}

int main () {
  int fd[2];

  // build up a global tracker of "processes" (contexts)
  proc_sync.count = 0;
  proc_sync.sync = dispatch_semaphore_create(0);
  proc_sync.q = dispatch_queue_create("sync", NULL);

  // Post an asynchronous block that waits on the process signal
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), 
		 ^{
		   dispatch_semaphore_wait(proc_sync.sync, DISPATCH_TIME_FOREVER);
		   exit(0);
		 });

  // Our blocks are dispatched based on pipe FDs.
  if (pipe(fd) != 0) {
    perror("Couldn't make the first pipe");
    abort();
  }
  setup_block(fd[0]);

  // Run the sieve proc
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{run_sieve(fd[1]);});
  
  // wait for all outstanding blocks on queues
  dispatch_main();
  return 0;
}

Annotation number 3: Don't write to uninitialized fds
Pasted by: Dave Leimbach
When:2 years, 8 months ago
Share:Tweet this! | http://paste.lisp.org/+1US5/3
Paste contents:
Raw Source | Display As
// David Leimbach
// September 4, 2009
//
// First, unclean attempt at a prime number sieve in C with libdispatch
//
// Special thanks to Kevin Van Vechten and Jordan Hubbard for guidance through this new API!
//
// Thanks to Apple for making Snow Leopard so affordable!

#include <dispatch/dispatch.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>

#if !defined(MAX)
#define MAX 700
#endif

#define LAST -1

struct context
{
  int mynum;
  int has_spawned;
  int writefd;
};

dispatch_group_t proc_group;

void cleanup_proc(void * p) {
  struct context * ctx = p;
  close(ctx->writefd);
  free(p);
  dispatch_group_leave(proc_group);
}

void setup_block(int read_fd) {
  dispatch_source_t piperead;
  struct context * ctx;
  piperead = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, read_fd,
				    0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0));

  ctx = calloc(sizeof(struct context), 1);

  ctx->has_spawned = 0;

  dispatch_source_set_event_handler(piperead, 
				    ^{
				      int val;
				      int fd[2];
				      struct context * ctx = dispatch_get_context(piperead);

				      read(read_fd, &val, 4);
				      
				      if (val != LAST) {
					if (ctx->has_spawned == 0) {
					  if (pipe(fd) != 0) {
					    perror("Please increase your ulimit for file descriptors\naborting...\n");
					    abort();
					  }
					  ctx->writefd = fd[1];
					  ctx->mynum = val;
					  ctx->has_spawned = 1;
					  setup_block(fd[0]);
					  printf("%d\n", val);
					}
					else {
					  if (val % ctx->mynum != 0) {
					    write(ctx->writefd, &val, 4);
					  }
					}
				      }
				      else {
					write(ctx->writefd, &val, 4);
					close(read_fd);
					dispatch_release(piperead);
				      }
				    });
  
  dispatch_set_context(piperead, ctx);  // associate this state with this context

  dispatch_set_finalizer_f(piperead, cleanup_proc);

  dispatch_group_enter(proc_group);
  
  dispatch_resume(piperead);
}


void run_sieve(int writefd) {
  int x;
  
  for(x=2; x <= MAX; ++x) {
    write(writefd, &x, 4);
  }
  //  sleep(10);
  x = LAST;
  write(writefd, &x, 4);
}

int main () {
  int fd[2];

  // build up a global tracker of "processes" (contexts)
  proc_group = dispatch_group_create();
	
  // Our blocks are dispatched based on pipe FDs.
  if (pipe(fd) != 0) {
    perror("Couldn't make the first pipe");
    abort();
  }
  setup_block(fd[0]);

  // Run the sieve proc
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{run_sieve(fd[1]);});

  // Post an asynchronous block that waits on the process signal
  dispatch_group_notify(proc_group, dispatch_get_main_queue(),
						^{
							fflush(stdout);
							exit(0);
						});
	
  // wait for all outstanding blocks on queues
  dispatch_main();
  return 0;
}

Annotation number 4: Fixed the ????
Pasted by: Dave Leimbach
When:2 years, 8 months ago
Share:Tweet this! | http://paste.lisp.org/+1US5/4
Paste contents:
Raw Source | Display As
// David Leimbach
// September 4, 2009
//
// First, unclean attempt at a prime number sieve in C with libdispatch
//
// Special thanks to Kevin Van Vechten and Jordan Hubbard for guidance through this new API!
//
// Thanks to Apple for making Snow Leopard so affordable!

#include <dispatch/dispatch.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>

#if !defined(MAX)
#define MAX 700
#endif

#define LAST -1

struct context
{
  int mynum;
  int has_spawned;
  int writefd;
};

dispatch_group_t proc_group;

void cleanup_proc(void * p) {
  struct context * ctx = p;
  close(ctx->writefd);
  free(p);
  dispatch_group_leave(proc_group);
}

void setup_block(int read_fd) {
  dispatch_source_t piperead;
  struct context * ctx;
  piperead = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, read_fd,
				    0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0));

  ctx = calloc(sizeof(struct context), 1);

  ctx->has_spawned = 0;

  dispatch_source_set_event_handler(piperead, 
				    ^{
				      int val;
				      int fd[2];
				      struct context * ctx = dispatch_get_context(piperead);

				      read(read_fd, &val, 4);
				      
				      if (val != LAST) {
					if (ctx->has_spawned == 0) {
					  if (pipe(fd) != 0) {
					    perror("Please increase your ulimit for file descriptors\naborting...\n");
					    abort();
					  }
					  ctx->writefd = fd[1];
					  ctx->mynum = val;
					  ctx->has_spawned = 1;
					  setup_block(fd[0]);
					  printf("%d\n", val);
					}
					else {
					  if (val % ctx->mynum != 0) {
					    write(ctx->writefd, &val, 4);
					  }
					}
				      }
				      else {
					if (ctx->has_spawned != 0) 
						write(ctx->writefd, &val, 4);
					close(read_fd);
					dispatch_release(piperead);
				      }
				    });
  
  dispatch_set_context(piperead, ctx);  // associate this state with this context

  dispatch_set_finalizer_f(piperead, cleanup_proc);

  dispatch_group_enter(proc_group);
  
  dispatch_resume(piperead);
}


void run_sieve(int writefd) {
  int x;
  
  for(x=2; x <= MAX; ++x) {
    write(writefd, &x, 4);
  }
  //  sleep(10);
  x = LAST;
  write(writefd, &x, 4);
}

int main () {
  int fd[2];

  // build up a global tracker of "processes" (contexts)
  proc_group = dispatch_group_create();
	
  // Our blocks are dispatched based on pipe FDs.
  if (pipe(fd) != 0) {
    perror("Couldn't make the first pipe");
    abort();
  }
  setup_block(fd[0]);

  // Run the sieve proc
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{run_sieve(fd[1]);});

  // Post an asynchronous block that waits on the process signal
  dispatch_group_notify(proc_group, dispatch_get_main_queue(),
						^{
							fflush(stdout);
							exit(0);
						});
	
  // wait for all outstanding blocks on queues
  dispatch_main();
  return 0;
}

Annotation number 5: No pipes, just blocks, groups and queues
Pasted by: David Leimbach
When:2 years, 8 months ago
Share:Tweet this! | http://paste.lisp.org/+1US5/5
Paste contents:
Raw Source | Display As
#include <dispatch/dispatch.h>
#include <stdio.h>
#include <stdlib.h>

#if !defined(MAX)
#define MAX 1000
#endif

#define LAST -1

dispatch_group_t group;

struct context
{
  int mynum;
  dispatch_queue_t neighbor;
  int has_spawned;
};


void * ecalloc (size_t count, size_t size) {
  void * rv = calloc(count, size);
  if (rv == NULL) {
    perror("Failed to allocate memory");
    abort();
  }
  return rv;
}

// Deallocates contexts on released queues
void cleanup_queue(void * p) {
  struct context * ctx = p;
  free(p);
  dispatch_group_leave(group);
}


// Creates queues and associated contexts
dispatch_queue_t create_queue(int mynum) {
  char * name;
  dispatch_queue_t rv;
  struct context * ctx;

  asprintf(&name, "%d", mynum);
  rv = dispatch_queue_create(name, NULL);

  ctx = (struct context *) ecalloc(sizeof(struct context), 1);
  ctx->mynum = mynum;
  ctx->has_spawned = 0;

  dispatch_set_context(rv, ctx);
  dispatch_set_finalizer_f(rv, cleanup_queue);
  dispatch_group_enter(group);

  return rv;
}
 

// Runs a block asynchronously on a queue
void run_block (dispatch_queue_t q, int cur_num) {
  dispatch_async(q, 
		 ^{
		   struct context * ctx = (struct context *) dispatch_get_context(q);
		   
		   if (cur_num == LAST) {
		     if (ctx->has_spawned == 1) {
		       run_block(ctx->neighbor, cur_num);
		     }
		     dispatch_release(q);
		   } 
		   else if (cur_num == ctx->mynum) {
		       printf("%d\n", cur_num);
		   }
		   else if (cur_num % ctx->mynum != 0) {
		     if (ctx->has_spawned == 0) {
		       ctx->neighbor = create_queue(cur_num);
		       ctx->has_spawned = 1;
		     }
		     run_block(ctx->neighbor, cur_num);
		   }
		  
		 });
}    

void run_sieve() {
  int x;
  dispatch_queue_t two_q;

  // First make a serial queue for the number 2 - our first number
  two_q = create_queue(2);

  // Next iterate over all the numbers between 2 and MAX, dispatching a block each time.

  for (x = 2; x <= MAX; ++x) {
    run_block(two_q, x);
  }
  run_block(two_q, LAST); // cause a cleanup
  //  dispatch_release(two_q);
}
  

int main () {
  group = dispatch_group_create();
  
  run_sieve();

  dispatch_group_notify(group, dispatch_get_main_queue(),
			^{
			  fflush(stdout);
			  exit(0);
			});

  dispatch_main();

  return 0;
}

Annotation number 6: no more define MAX. Setting target queue
Pasted by: David Leimbach
When:2 years, 8 months ago
Share:Tweet this! | http://paste.lisp.org/+1US5/6
Paste contents:
Raw Source | Display As
#include <dispatch/dispatch.h>
#include <stdio.h>
#include <stdlib.h>

#define LAST -1

dispatch_group_t group;

struct context
{
  int mynum;
  dispatch_queue_t neighbor;
  int has_spawned;
};


void * ecalloc (size_t count, size_t size) {
  void * rv = calloc(count, size);
  if (rv == NULL) {
    perror("Failed to allocate memory");
    abort();
  }
  return rv;
}

// Deallocates contexts on released queues
void cleanup_queue(void * p) {
  struct context * ctx = p;
  free(p);
  dispatch_group_leave(group);
}


// Creates queues and associated contexts
dispatch_queue_t create_queue(int mynum) {
  char * name;
  dispatch_queue_t rv;
  struct context * ctx;

  asprintf(&name, "%d", mynum);
  rv = dispatch_queue_create(name, NULL);

  ctx = (struct context *) ecalloc(sizeof(struct context), 1);
  ctx->mynum = mynum;
  ctx->has_spawned = 0;

  dispatch_set_context(rv, ctx);
  dispatch_set_finalizer_f(rv, cleanup_queue);
  dispatch_group_enter(group);

  dispatch_set_target_queue(rv, dispatch_get_global_queue(0,0));

  return rv;
}
 

// Runs a block asynchronously on a queue
void run_block (dispatch_queue_t q, int cur_num) {
  dispatch_async(q, 
		 ^{
		   struct context * ctx = (struct context *) dispatch_get_context(q);
		   
		   if (cur_num == LAST) {
		     if (ctx->has_spawned == 1) {
		       run_block(ctx->neighbor, cur_num);
		     }
		     dispatch_release(q);
		   } 
		   else if (cur_num == ctx->mynum) {
		       printf("%d\n", cur_num);
		   }
		   else if (cur_num % ctx->mynum != 0) {
		     if (ctx->has_spawned == 0) {
		       ctx->neighbor = create_queue(cur_num);
		       ctx->has_spawned = 1;
		     }
		     run_block(ctx->neighbor, cur_num);
		   }
		  
		 });
}    

void run_sieve(int max) {
  int x;
  dispatch_queue_t two_q;

  // First make a serial queue for the number 2 - our first number
  two_q = create_queue(2);

  // Next iterate over all the numbers between 2 and MAX, dispatching a block each time.

  for (x = 2; x <= max; ++x) {
    run_block(two_q, x);
  }
  run_block(two_q, LAST); // cause a cleanup
}
  
void usage(){
  printf("Please provide an integer for the max prime to calculate\n");
}

int main (int argc, char ** argv) {
  int max;

  if (argc != 2) {
    usage();
    return -1;
  }

  max = atoi(argv[1]);

  group = dispatch_group_create();
  
  run_sieve(max);

  dispatch_group_notify(group, dispatch_get_main_queue(),
			^{
			  fflush(stdout);
			  exit(0);
			});

  dispatch_main();

  return 0;
}

Annotation number 7: no more blocks to copy for each work item.
Pasted by: David Leimbach
When:2 years, 8 months ago
Share:Tweet this! | http://paste.lisp.org/+1US5/7
Paste contents:
Raw Source | Display As
#include <dispatch/dispatch.h>
#include <stdio.h>
#include <stdlib.h>

#define LAST -1

dispatch_group_t group;

struct context
{
  int mynum;
  dispatch_queue_t neighbor;
  int has_spawned;
};


void * ecalloc (size_t count, size_t size) {
  void * rv = calloc(count, size);
  if (rv == NULL) {
    perror("Failed to allocate memory");
    abort();
  }
  return rv;
}

// Deallocates contexts on released queues
void cleanup_queue(void * p) {
  struct context * ctx = p;
  free(p);
  dispatch_group_leave(group);
}


// Creates queues and associated contexts
dispatch_queue_t create_queue(int mynum) {
  char * name;
  dispatch_queue_t rv;
  struct context * ctx;

  asprintf(&name, "%d", mynum);
  rv = dispatch_queue_create(name, NULL);

  ctx = (struct context *) ecalloc(sizeof(struct context), 1);
  ctx->mynum = mynum;
  ctx->has_spawned = 0;

  dispatch_set_context(rv, ctx);
  dispatch_set_finalizer_f(rv, cleanup_queue);
  dispatch_group_enter(group);

  dispatch_set_target_queue(rv, dispatch_get_global_queue(0,0));

  return rv;
}
 

void worker (void * fctx) {
  int cur_num = (int) fctx;  // bad bad bad, but I don't care.
  dispatch_queue_t cur_q = dispatch_get_current_queue();
  struct context * qctx = (struct context *) dispatch_get_context(cur_q);
  
  if (cur_num == LAST) {
    if (qctx->has_spawned == 1) {
      dispatch_async_f(qctx->neighbor, (void *)cur_num, worker);
    }
    dispatch_release(cur_q);
  } 
  else if (cur_num == qctx->mynum) {
    printf("%d\n", cur_num);
  }
  else if (cur_num % qctx->mynum != 0) {
    if (qctx->has_spawned == 0) {
      qctx->neighbor = create_queue(cur_num);
      qctx->has_spawned = 1;
    }
    dispatch_async_f(qctx->neighbor, (void *)cur_num, worker);
  }
}
  
void run_sieve(int max) {
  int x;
  dispatch_queue_t two_q;

  // First make a serial queue for the number 2 - our first number
  two_q = create_queue(2);

  // Next iterate over all the numbers between 2 and MAX, dispatching a block each time.

  for (x = 2; x <= max; ++x) {
    dispatch_async_f(two_q, (void *)x, worker);
  }
  dispatch_async_f(two_q, (void *)LAST, worker); // cause a cleanup
}
  
void usage(){
  printf("Please provide an integer for the max prime to calculate\n");
}

int main (int argc, char ** argv) {
  int max;

  if (argc != 2) {
    usage();
    return -1;
  }

  max = atoi(argv[1]);

  group = dispatch_group_create();
  
  run_sieve(max);

  dispatch_group_notify(group, dispatch_get_main_queue(),
			^{
			  fflush(stdout);
			  exit(0);
			});

  dispatch_main();

  return 0;
}

Colorize as:
Show Line Numbers
Index of paste annotations: 1 | 2 | 3 | 4 | 5 | 6 | 7

Lisppaste pastes can be made by anyone at any time. Imagine a fearsomely comprehensive disclaimer of liability. Now fear, comprehensively.