Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Node.js timer #3

Open
hustxiaoc opened this issue Oct 12, 2014 · 1 comment
Open

Node.js timer #3

hustxiaoc opened this issue Oct 12, 2014 · 1 comment

Comments

@hustxiaoc
Copy link
Owner

a simple timer based on kqueue and min binary heap

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/event.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>

//https://github.com/joyent/libuv/blob/master/src/heap-inl.h
#include "heap-inl.h"

#define container_of(ptr, type, member) \
  ((type *) ((char *) (ptr) - offsetof(type, member)))

const int MAX_EVENT_COUNT = 5000;

typedef struct {
    struct heap_node* heap_node[3];
    int value;
}node_t;

static int less_than(const struct heap_node* ha, const struct heap_node* hb) {
    const node_t* a;
      const node_t* b;

    a = container_of(ha, const node_t, heap_node);
    b = container_of(hb, const node_t, heap_node);

    if (a->value < b->value)
      return 1;
    return 0;
}


int main() {

  struct heap *heap_p = malloc(sizeof(node_t));
  heap_init(heap_p);

  int a[] = {10,9,8,6,7,3,5,4,2};

  int len = sizeof(a)/sizeof(int);
  for(int i=0;i<len;i++){
    node_t *node_p = malloc(sizeof(node_t));
    node_p->value = a[i]*1000;
    heap_insert(heap_p, (struct heap_node*)node_p->heap_node, less_than);
  }


  int fd = socket(PF_INET, SOCK_STREAM,0);
  int kq = kqueue();

  struct kevent changes[1];
  EV_SET(&changes[0], fd, EVFILT_READ, EV_ADD, 0, 0, NULL);

  struct kevent events[MAX_EVENT_COUNT];
  time_t last_time = time(NULL);
  while(heap_p->nelts) {
      node_t *node_p = container_of(heap_p->min, node_t, heap_node);
      struct timespec spec;
      spec.tv_sec = node_p->value / 1000;
      spec.tv_nsec = (node_p->value % 1000) * 1000000;
      kevent(kq, NULL, 0, events, MAX_EVENT_COUNT, &spec);
      heap_dequeue(heap_p, less_than);
      printf("timeout = %d, run time is %ld\n", node_p->value, time(NULL)-last_time);
      last_time = time(NULL);
  }

  printf("timer is over!\n");

  return 0;
}

run the code ,you'll get

timeout = 2000, run time is 2
timeout = 3000, run time is 3
timeout = 4000, run time is 4
timeout = 5000, run time is 5
timeout = 6000, run time is 6
timeout = 7000, run time is 7
timeout = 8000, run time is 8
timeout = 9000, run time is 9
timeout = 10000, run time is 10
timer is over!

exactly as we expected!

@hustxiaoc hustxiaoc changed the title node .js timer Node.js timer Oct 12, 2014
@hustxiaoc
Copy link
Owner Author

/*
Swap parent with child. Child moves closer to the root, parent moves away.
the official heap_node_swap actually just moves the pointer but it indeed does not have a data pointer. and heap_node_swap below moves both, the pointer self and it's data pointer
*/

static void heap_node_swap(struct heap* heap,
                           struct heap_node* parent,
                           struct heap_node* child) {
  int left;
  struct heap_node* sibling;

  child->parent = parent->parent;
  parent->parent = child;

  if(child->parent != NULL) {
    if(child->parent->left == parent) {
        child->parent->left = child;
    }else{
        child->parent->right = child;
    }
  }else {
    heap->min = child;
  }

  left = (parent->left == child)? 1:0;

  sibling = left ? parent->right: parent->left;

  parent->left = child->left;
  parent->right = child->right;
  if(child->left != NULL) {
     parent->left->parent = parent;
  }
   if(child->right != NULL) {
    parent->right->parent = parent;
  }

  if(left) {
      child->left = parent;
      child->right = sibling;
  }else{
      child->right = parent;
      child->left = sibling;
  }

  if(sibling != NULL) {
      sibling->parent = child;
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant