Jump to content

coroutine


Mahlukat

Recommended Posts

Hey
i have a export function for dbQuery
but when i call func, data from database stay late

I searched the forum and found a few solutions with coroutine

but I could not :((
anyone can explain how's work coroutine and what should i do please

function querydb(str)
	if str:find("DROP TABLE") then return end
	local id = getFreeID()
	local co = nil
	function verileriAktar(sorgu)
		coroutine.resume(co, sorgu) 
	end
	co = coroutine.create(function() 
		dbQuery(verileriAktar,connection,str) 
		local results = coroutine.yield() 
		local cevap = dbPoll(results,0)
		queries[id] = cevap 
		print(id) 
	end) 
	coroutine.resume(co)
	-- should stop here i guess but its not
	print("cevap: "..id)	
	return id 
end

local id = querydb("SOME DB CODES")
-- cevap: 1
-- 1

 

Link to comment
  • Moderators

This is not how you use coroutines. Databases and coroutines are two very different things. But for what kind of reason do you want to use a coroutines?

 

dbQuery is already providing you with a callback option.

https://wiki.multitheftauto.com/wiki/DbQuery

Optional Arguments

  • callbackFunction: An optional function to be called when a result is ready. The function will only be called if the result has not already been read with dbPoll. The function is called with the query handle as the first argument. (Notice: Do not use a function with a local prefix)

 

If you want to improve your database performance, then write better queries with limiters.

Link to comment
34 minutes ago, IIYAMA said:

But for what kind of reason do you want to use a coroutines?

Thanks you for your answer

When i call querydb function, its return before dbQuery's callback function

and i thought maybe querydb function can wait for dbQuery's callback function

because i have a another function like this;

function getQueryResult(id)
	if not queries[id] then return false end
	return queries[id]
end	

I am using exactly like this;

local id = querydb("SOME DB FUNCS")
local result = getQueryResult(id)

 

Link to comment
  • Moderators

You can do that, but the coroutine has to be placed around this:

-- couroutine function

local id = querydb("SOME DB FUNCS")
local result = getQueryResult(id)

--

 

function something ()
  local co = coroutine.create(function ()
      local id = querydb(co, "query")
      
      local result = querydb(co, "query")
  end)
  coroutine.resume(co) -- start the coroutine
end

function querydb (co, query)
  
  -- ...
  
  local callBackFunction = function ()
    coroutine.resume(co) -- resume!
  end	
  
  -- execute the query here!
  
  coroutine.yield() -- freeze!
  
  return results
end

 

Something like that.

 

  • Thanks 1
Link to comment
  • Moderators

A coroutine is a function block which can be frozen with:

 coroutine.yield()

This function has to be called during the execution of the block. It doesn't have to be in the same block, but within the code that is executed in the block.

 

 

 

The resume function can be called from where ever you want. It can be used to start the executing the coroutine function. But also to resume a frozen(yield) coroutine function.

coroutine.resume(co)

When a coroutine function has been executed till the end, the status of the coroutine function is considered dead. It can't be resumed any more.

 

 

  • Thanks 1
Link to comment

I believe coroutines cannot be sent over via callback arguments, so you'll have to store the coroutine reference in a table t at some index i and then send i for callback, and resume t[ i ] in the callback function.

gDatabaseConnection = --[[ this would be your database connection here ]]

local coroutines = {} -- coroutines will be stored here

function gCallbackFn(qh, id) -- this is called when dbQuery thread returns indicating the query is ready to poll
  local result = dbPoll(qh, 0) -- since it's ready to poll, timeout is irrelevant and can be 0
  coroutine.resume(coroutines[id], result) -- resume the coroutine with query result data
end

function handleQuery(queryStr, ...)
  if not coroutine.running() then error("handleQuery can only be called from within a coroutine.", 2) end
  
  local id = table.maxn(coroutines) + 1 -- calculate next unused table index (not sure whether # or maxn is better here)
  coroutines[id] = coroutine.running() -- store this coroutine in that table index
  
  dbQuery(gCallbackFn, {id}, gDatabaseConnection, queryStr, ...) -- this splits into two threads, first one continutes over to coroutine.yield function, other is internal to MTA and handles the query, and continues from gCallbackFn afterwards.
  
  local qData = coroutine.yield() -- since we want to wait for the query thread to return, we need to yield/pause this coroutine execution, and let gCallbackFn resume it when the query thread returns
  
  return qData -- return the query result data
end

-- now call handleQuery at some arbitrary point, here, after 1000ms (1s)
c = coroutine.wrap( -- coroutine.wrap creates a coroutine wrapped in a function that, when called, will start/resume the coroutine
  function()
    local result = handleQuery("SELECT * sometable WHERE id = ?", 2)
    iprint(result)
  end
)
setTimer(c, 1000, 1) -- call the function-wrapped coroutine after 1000ms

I've only tested this using timers instead of dbQuery but it should work.

N.B. this handleQuery function must be called from within a coroutine. If you're calling this when an event happens, you can override addEventHandler to automatically wrap handlers into coroutines too.

local addEventHandler_ = addEventHandler
function addEventHandler(eventName, attachedTo, handlerFn, propagation, priority)
  return addEventHandler_(eventName, attachedTo, coroutine.wrap(handlerFn), propagation, priority)
end

 

Edited by MrTasty
  • Thanks 1
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...