billywhizz
11/17/2010 - 3:08 AM

binder.cc

var Binder = require("./lib/binder").Binder;

var binder = new Binder();

binder.onCall = function(message) {
	counter++;
};

var counter = 0;
var then = new Date().getTime();
var runs = process.ARGV[2];
for(var i=0; i<runs; i++) {
	binder.callMe("hello");
}
var now = new Date().getTime();
var elapsed = ((now - then)/1000).toFixed(3);

console.log("early-bound: " + counter + " in " + elapsed + " seconds. ops/sec: " + (counter / elapsed).toFixed(2));

var counter = 0;
var then = new Date().getTime();
var runs = process.ARGV[2];
for(var i=0; i<runs; i++) {
	binder.callMe2("hello");
}
var now = new Date().getTime();
var elapsed = ((now - then)/1000).toFixed(3);

console.log("late-bound: " + counter + " in " + elapsed + " seconds. ops/sec: " + (counter / elapsed).toFixed(2));
#include <node.h>
#include <node_buffer.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>

using namespace v8;
using namespace node;

static Persistent<String> on_call_sym;

class Binder : public ObjectWrap {
	private:
		Persistent<Function> _cb;
		bool _bound;
	public:
		static void Initialize (v8::Handle<v8::Object> target)
		{
			HandleScope scope;
			Local<FunctionTemplate> t = FunctionTemplate::New(New);
			t->InstanceTemplate()->SetInternalFieldCount(1);
			NODE_SET_PROTOTYPE_METHOD(t, "callMe", CallMe);
			NODE_SET_PROTOTYPE_METHOD(t, "callMe2", CallMe2);
			on_call_sym = NODE_PSYMBOL("onCall");

			target->Set(String::NewSymbol("Binder"), t->GetFunction());
		}

	protected:

		static Handle<Value> New (const Arguments& args)
		{
			HandleScope scope;
			Binder *binder = new Binder();
			binder->Wrap(args.This());
			return args.This();
		}

		static Handle<Value> CallMe2(const Arguments &args) {
			HandleScope scope;
			Binder *binder = ObjectWrap::Unwrap<Binder>(args.This());
		
			if (!args[0]->IsString()) {
				return ThrowException(Exception::TypeError(String::New("Argument must be a string")));
			}

		    Local<Value> cb_value = binder->handle_->Get(on_call_sym);
			Local<Function> cb;
			if (cb_value->IsFunction()) {
		    	cb = Local<Function>::Cast(cb_value);
				Local<Value> argv[1] = {args[0]->ToString()};
				Local<Value> retval = cb->Call(binder->handle_, 1, argv);
			}
			
			String::AsciiValue format(args[0]->ToString());
			return scope.Close(Integer::New(0));
		}

		static Handle<Value> CallMe(const Arguments &args) {
			HandleScope scope;
			Binder *binder = ObjectWrap::Unwrap<Binder>(args.This());
		
			if (!args[0]->IsString()) {
				return ThrowException(Exception::TypeError(String::New("Argument must be a string")));
			}

		    if(!binder->_bound) {
				printf("binding\n");
				Local<Value> cb_value = binder->handle_->Get(on_call_sym);
				if (cb_value->IsFunction()) {
			    	binder->_cb = Persistent<Function>::New(Local<Function>::Cast(cb_value));
					binder->_bound = true;
				}
			}
			
			Local<Value> argv[1] = {args[0]->ToString()};
			Local<Value> retval = binder->_cb->Call(binder->handle_, 1, argv);

			String::AsciiValue format(args[0]->ToString());
			return scope.Close(Integer::New(0));
		}


		Binder () : ObjectWrap () 
		{
		}

		~Binder ()
		{
		}
};

extern "C" void
init (Handle<Object> target) 
{
  HandleScope scope;
  Binder::Initialize(target);
}