Merge branch 'dev' of github.com:cloudwu/skynet into dev

This commit is contained in:
Cloud Wu
2014-12-08 10:53:53 +08:00
3 changed files with 77 additions and 51 deletions

View File

@@ -227,6 +227,10 @@ function mongo_collection:insert(doc)
sock:request(pack) sock:request(pack)
end end
function mongo_collection:safe_insert(doc)
return self.database:runCommand("insert", self.name, "documents", {bson_encode(doc)})
end
function mongo_collection:batch_insert(docs) function mongo_collection:batch_insert(docs)
for i=1,#docs do for i=1,#docs do
if docs[i]._id == nil then if docs[i]._id == nil then
@@ -276,6 +280,48 @@ function mongo_collection:find(query, selector)
} , cursor_meta) } , cursor_meta)
end end
-- collection:createIndex({username = 1}, {unique = true})
function mongo_collection:createIndex(keys, option)
local name
for k, v in pairs(keys) do
assert(v == 1)
name = (name == nil) and k or (name .. "_" .. k)
end
local doc = {};
doc.name = name
doc.key = keys
for k, v in pairs(option) do
if v then
doc[k] = true
end
end
return self.database:runCommand("createIndexes", self.name, "indexes", {doc})
end
mongo_collection.ensureIndex = mongo_collection.createIndex;
-- collection:findAndModify({query = {name = "userid"}, update = {["$inc"] = {nextid = 1}}, })
-- keys, value type
-- query, table
-- sort, table
-- remove, bool
-- update, table
-- new, bool
-- fields, bool
-- upsert, boolean
function mongo_collection:findAndModify(doc)
assert(doc.query)
assert(doc.update or doc.remove)
local cmd = {"findAndModify", self.name};
for k, v in pairs(doc) do
table.insert(cmd, k)
table.insert(cmd, v)
end
return self.database:runCommand(unpack(cmd))
end
function mongo_cursor:hasNext() function mongo_cursor:hasNext()
if self.__ptr == nil then if self.__ptr == nil then
if self.__document == nil then if self.__document == nil then

View File

@@ -32,12 +32,9 @@ struct message_queue {
}; };
struct global_queue { struct global_queue {
uint32_t head; struct message_queue *head;
uint32_t tail; struct message_queue *tail;
struct message_queue ** queue; int lock;
// We use a separated flag array to ensure the mq is pushed.
// See the comments below.
struct message_queue *list;
}; };
static struct global_queue *Q = NULL; static struct global_queue *Q = NULL;
@@ -51,57 +48,32 @@ void
skynet_globalmq_push(struct message_queue * queue) { skynet_globalmq_push(struct message_queue * queue) {
struct global_queue *q= Q; struct global_queue *q= Q;
uint32_t tail = GP(__sync_fetch_and_add(&q->tail,1)); LOCK(q)
assert(queue->next == NULL);
// only one thread can set the slot (change q->queue[tail] from NULL to queue) if(q->tail) {
if (!__sync_bool_compare_and_swap(&q->queue[tail], NULL, queue)) { q->tail->next = queue;
// The queue may full seldom, save queue in list q->tail = queue;
assert(queue->next == NULL); } else {
struct message_queue * last; q->head = q->tail = queue;
do {
last = q->list;
queue->next = last;
} while(!__sync_bool_compare_and_swap(&q->list, last, queue));
return;
} }
UNLOCK(q)
} }
struct message_queue * struct message_queue *
skynet_globalmq_pop() { skynet_globalmq_pop() {
struct global_queue *q = Q; struct global_queue *q = Q;
uint32_t head = q->head;
if (head == q->tail) { LOCK(q)
// The queue is empty. struct message_queue *mq = q->head;
return NULL; if(mq) {
} q->head = mq->next;
if(q->head == NULL) {
uint32_t head_ptr = GP(head); assert(mq == q->tail);
q->tail = NULL;
struct message_queue * list = q->list;
if (list) {
// If q->list is not empty, try to load it back to the queue
struct message_queue *newhead = list->next;
if (__sync_bool_compare_and_swap(&q->list, list, newhead)) {
// try load list only once, if success , push it back to the queue.
list->next = NULL;
skynet_globalmq_push(list);
} }
mq->next = NULL;
} }
UNLOCK(q)
struct message_queue * mq = q->queue[head_ptr];
if (mq == NULL) {
// globalmq push not complete
return NULL;
}
if (!__sync_bool_compare_and_swap(&q->head, head, head+1)) {
return NULL;
}
// only one thread can get the slot (change q->queue[head_ptr] to NULL)
if (!__sync_bool_compare_and_swap(&q->queue[head_ptr], mq, NULL)) {
return NULL;
}
return mq; return mq;
} }
@@ -243,8 +215,6 @@ void
skynet_mq_init() { skynet_mq_init() {
struct global_queue *q = skynet_malloc(sizeof(*q)); struct global_queue *q = skynet_malloc(sizeof(*q));
memset(q,0,sizeof(*q)); memset(q,0,sizeof(*q));
q->queue = skynet_malloc(MAX_GLOBAL_MQ * sizeof(struct message_queue *));
memset(q->queue, 0, sizeof(struct message_queue *) * MAX_GLOBAL_MQ);
Q=q; Q=q;
} }

10
test/testdeadloop.lua Normal file
View File

@@ -0,0 +1,10 @@
local skynet = require "skynet"
local function dead_loop()
while true do
skynet.sleep(0)
end
end
skynet.start(function()
skynet.fork(dead_loop)
end)