예제 #1
0
/*
	userdata send_buffer
	table pool
	lightuserdata msg
	int size

	return size

	Comment: The table pool record all the buffers chunk, 
	and the first index [1] is a lightuserdata : free_node. We can always use this pointer for struct buffer_node .
	The following ([2] ...)  userdatas in table pool is the buffer chunk (for struct buffer_node), 
	we never free them until the VM closed. The size of first chunk ([2]) is 8 struct buffer_node,
	and the second size is 16 ... The largest size of chunk is LARGE_PAGE_NODE (4096)

	lpushbbuffer will get a free struct buffer_node from table pool, and then put the msg/size in it.
	lpopbuffer return the struct buffer_node back to table pool (By calling return_free_node).
 */
static int
lpushbuffer(lua_State *L) {
	struct socket_buffer *sb = lua_touserdata(L,1);
	if (sb == NULL) {
		return luaL_error(L, "need buffer object at param 1");
	}
	char * msg = lua_touserdata(L,3);
	if (msg == NULL) {
		return luaL_error(L, "need message block at param 3");
	}
	int pool_index = 2;
	luaL_checktype(L,pool_index,LUA_TTABLE);
	int sz = luaL_checkinteger(L,4);
	lua_rawgeti(L,pool_index,1);
	struct buffer_node * free_node = lua_touserdata(L,-1);	// sb poolt msg size free_node
	lua_pop(L,1);
	if (free_node == NULL) {
		int tsz = lua_rawlen(L,pool_index);
		if (tsz == 0)
			tsz++;
		int size = 8;
		if (tsz <= LARGE_PAGE_NODE-3) {
			size <<= tsz;
		} else {
			size <<= LARGE_PAGE_NODE-3;
		}
		lnewpool(L, size);	
		free_node = lua_touserdata(L,-1);
		lua_rawseti(L, pool_index, tsz+1);
	}
	lua_pushlightuserdata(L, free_node->next);	
	lua_rawseti(L, pool_index, 1);	// sb poolt msg size
	free_node->msg = msg;
	free_node->sz = sz;
	free_node->next = NULL;

	if (sb->head == NULL) {
		assert(sb->tail == NULL);
		sb->head = sb->tail = free_node;
	} else {
		sb->tail->next = free_node;
		sb->tail = free_node;
	}
	sb->size += sz;

	lua_pushinteger(L, sb->size);

	return 1;
}
예제 #2
0
 // local sz = driver.push(s.buffer, buffer_pool, data, size)
static int
lpushbuffer(lua_State *L) {
	// 获取第一个参数值,缓冲区链表
	struct socket_buffer *sb = lua_touserdata(L,1);
	if (sb == NULL) {
		return luaL_error(L, "need buffer object at param 1");
	}
	// 获取第三个参数值,消息数据
	char * msg = lua_touserdata(L,3);
	if (msg == NULL) {
		return luaL_error(L, "need message block at param 3");
	}
	int pool_index = 2;
	// 检查第二个参数是否为table类型
	/*
		local buffer_pool = {}
		buffer_pool是在lua层(socket.lua)中创建并初始化空表
		lua方法pop,push,readall,readline,clear中作为第二个参数传入
		在lua绑定的c方法中,从栈中取出第二个元素,即可得到buffer_pool

		buffer_pool[1],存放的是一个lightuserdata,即缓冲区池第一个节点的地址,见lua_pushlightuserdata(L, free_node->next);	
		buffer_pool[2] ...,存放的是userdata,即固定大小的链表数组内存地址,见lua_rawseti(L, pool_index, tsz+1);
	*/
	luaL_checktype(L,pool_index,LUA_TTABLE);
	// 获取第四个参数值,消息长度
	int sz = luaL_checkinteger(L,4);
	// 把缓冲池lua表的第一个元素压栈
	lua_rawgeti(L,pool_index,1);
	// 获取缓冲池lua表的第一个元素
	// 准确地说是 获取第一个元素存放的指针 所指向的一段完全用户数据 其实就是一个缓冲区节点
	struct buffer_node * free_node = lua_touserdata(L,-1);	// sb poolt msg size free_node
	// 把缓冲池lua表的第一个元素弹出栈
	lua_pop(L,1);
	if (free_node == NULL) {
		// 如果获取到的缓冲区节点为空,说明buffer_pool[n]里的buffer_node已经用光

		// 获取buffer_pool表的长度
		// 初始为0,一直递增,直到vm重启
		/*
			tsz buffer_pool表的长度
			index buffer_pool表的索引
			size buffer_pool[index]存放buffer_node的数量
		
			tsz  size          index
			0    8 << 1 = 16   2
			2    8 << 2 = 32   3
			.
			.
			.
			9    8 << 9 = 4096 10
			10   8 << 9 = 4096 11
		*/
		int tsz = lua_rawlen(L,pool_index);
		if (tsz == 0)
			// 初始为0,预留buffer_pool[1]存放lightuserdata
			tsz++;
		int size = 8;
		if (tsz <= LARGE_PAGE_NODE-3) {
			size <<= tsz;
		} else {
			// 不超过4096,即2的12次方
			size <<= LARGE_PAGE_NODE-3;
		}
		// 新建缓冲区池
		// struct buffer_node * pool = lua_newuserdata(L, sizeof(struct buffer_node) * sz);
		lnewpool(L, size);	
		// 获取新建缓冲区池第一个缓冲区节点
		free_node = lua_touserdata(L,-1);
		// 把新建的缓冲区池放到缓冲区池lua表的特定索引中
		lua_rawseti(L, pool_index, tsz+1);
	}
	// 把缓冲池lua表的第一个元素的下一个元素压栈
	lua_pushlightuserdata(L, free_node->next);	
	// 把缓冲池lua表的第一个元素的下一个元素设置为lua表的第一个元素,并弹出栈
	lua_rawseti(L, pool_index, 1);	// sb poolt msg size

	// 以上操作从缓冲池中取出了一个缓冲区节点

	// 缓冲区节点装入数据
	free_node->msg = msg;
	free_node->sz = sz;
	free_node->next = NULL;

	// 缓冲区节点加入链表
	if (sb->head == NULL) {
		assert(sb->tail == NULL);
		sb->head = sb->tail = free_node;
	} else {
		sb->tail->next = free_node;
		sb->tail = free_node;
	}
	sb->size += sz;

	// 缓冲区链表数据总长度压栈并作为lua返回值
	lua_pushinteger(L, sb->size);

	return 1;
}