This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
theoriginalbit's profile picture

Empty Tables

Started by theoriginalbit, 14 December 2012 - 12:13 AM
theoriginalbit #1
Posted 14 December 2012 - 01:13 AM
The source: http://pastebin.com/JNp3nJkg

The error: I keep getting "bios:267: Attempt to write to global" and I cannot track down the source


What I thought was the problem: EDIT: Seems like it might not be this.
SpoilerOk I'm attempting to do some processing on a table but only when there is data in it. I have 2 threads, one is populating the table with data from a network connection, the other is processing the data in the table one at a time and removing it when done. I am having some issues at the moment checking if the table is empty. I have done everything I know possible, and even Googled how to do it, but all methods of checking return this "bios:267: Attempt to write to global". I have tried the following:



-- Table declaration
tasks = {}

-- Method of inserting
table.insert(tasks, message)

-- Attempt 1
function empty (self)
	for _, _ in pairs(self) do
		return false
	end
	return true
end
local function processor()
while true do
  if (not empty(tasks)) then
   -- Do stuff
  end
end
end

-- Attempt 2
local function processor()
while true do
  if (#tasks == 0) then
   -- Do stuff
  end
end
end

-- Attempt 3
local function processor()
while true do
  if (table.len(tasks) == 0) then
   -- Do stuff
  end
end
end

-- Attempt 4
local function processor()
while true do
  if ( not (next(tasks) == nil )) then
   -- Do stuff
  end
end
end

-- Attempt 5
local function processor()
while true do
  if ( next(tasks) ~= nil ) then
   -- Do stuff
  end
end
end

-- Attempt 6 (I knew this wouldn't work due to my extensive knowledge in both procedural and OO programming, but I figured hey lets try everything)
local function processor()
while true do
  if ( tasks == {} )) then
   -- Do stuff
  end
end
end

Any help here would be great. :)/>
huettner94 #2
Posted 14 December 2012 - 03:54 AM
try:

if (type(tasks) ~= "table") then
  -- do stuff if the table is empty
end
Lyqyd #3
Posted 14 December 2012 - 04:30 AM
If you're only supposed to process while there is data in the table, why are you checking that it's empty before doing stuff? Try something like if #tasks > 0 then.
theoriginalbit #4
Posted 14 December 2012 - 04:32 AM
try:

if (type(tasks) ~= "table") then
  -- do stuff if the table is empty
end

Nope that didn't seem to work. I might edit the original post to include all the source. Maybe it isn't that causing the error, but it only occurred since I added it.
theoriginalbit #5
Posted 14 December 2012 - 01:30 PM
If you're only supposed to process while there is data in the table, why are you checking that it's empty before doing stuff? Try something like if #tasks > 0 then.

Nope that didn't help the error. It does fix a logical bug. But the error still exists. I've added the whole program source to the original post. :)/>
Lyqyd #6
Posted 14 December 2012 - 03:07 PM
If you're not set on using parallel unnecessarily:


function generateRandCardNumber(suffix)
	if (suffix == nil) then error("Expected 4 digit number got nil") end
	
	block1 = "6218"
	
	block2 = tostring(math.ceil(math.random() * math.pow(10,8)))
	for i = #block2, 3 do
		block2 = block2..i
	end
	
	block3 = tostring(math.ceil(math.random() * math.pow(10,4)))
	for i = #block3, 3 do
		block3 = block3..i
	end
	
	return block1.." "..block2.." "..block3.." "..suffix
end

term.clear()
term.setCursorPos(1, 1)

rednet.open("left")

local resumeTimer = os.startTimer(0.1)
local tasks = {}
local x, y

while true do
	event = {os.pullEvent()}
	if event[1] == "rednet_message" then
		if string.match(event[3], "^%[Card-Request%]") then
			table.insert(tasks, string.match(event[3],"^%[Card-Request%](.*)"))
		end
	elseif event[1] == "timer" then
		if #tasks > 0 then
			if not disk.isPresent("right") do
				x, y = term.getCursorPos()
				write("Waiting for new 'card'...")
				term.setCursorPos(x, y)
				resumeTimer = os.startTimer(0.1)
			else
				print("\nWriting to card...")
				cardNum = generateRandCardNumber(tasks[1])
				cardNum = generateRandCardNumber(tasks[1])
				disk.setLabel("right", cardNum)
				print("Card number: "..cardNum)
				print("Ejecting card...")
				disk.eject("right")
				print("Card Complete, moving on to next request.")
				table.remove(tasks, 1)
				resumeTimer = os.startTimer(0.1)
			end
		else
			x, y = term.getCursorPos()
			write("Waiting for request...")
			term.setCursorPos(x, y)
		end
	end
end

rednet.close("left")
theoriginalbit #7
Posted 14 December 2012 - 04:26 PM
If you're not set on using parallel unnecessarily:

The main reason I was using parallel was I plan on using this system extensively from a lot of computers and I wanted it so that if it was waiting for a new card it could still receive requests from other machines.

Im not getting the global error anymore, however it doesn't seem to get past this line:



if string.match(event[3], "^%[Card-Request%]") then

If I change it to this it will run, but it doesn't insert the value into the table.


if string.match(event[3],"[Card-Request](.*)") then
Lyqyd #8
Posted 14 December 2012 - 04:45 PM
If you're not set on using parallel unnecessarily:

The main reason I was using parallel was I plan on using this system extensively from a lot of computers and I wanted it so that if it was waiting for a new card it could still receive requests from other machines.

The version I posted does this as well.

Im not getting the global error anymore, however it doesn't seem to get past this line:



if string.match(event[3], "^%[Card-Request%]") then

If I change it to this it will run, but it doesn't insert the value into the table.


if string.match(event[3],"[Card-Request](.*)") then

That's not going to be a valid pattern. Is it giving you an error at that line? I'll try to play around with it that match a bit and see what's going on. It would be easier if you used angle braces rather than square ones, but that match I had should have worked fine.
theoriginalbit #9
Posted 14 December 2012 - 04:53 PM
The version I posted does this as well.

It seems to me that when it is processing the data and making the card it cannot be receiving a message at the same time via rednet, unless my understanding of os.pullEvent was 100% wrong.

That's not going to be a valid pattern. Is it giving you an error at that line? I'll try to play around with it that match a bit and see what's going on. It would be easier if you used angle braces rather than square ones, but that match I had should have worked fine.

Yeh I understand its not a valid pattern, but using print() I found that with that pattern it would not fire the if statement, and with no pattern it would fire but not add it into the table, the #table would still read 0
Lyqyd #10
Posted 14 December 2012 - 05:29 PM
Corrected code; note that I forgot to escape the hyphen the first time.


function generateRandCardNumber(suffix)
	    if (suffix == nil) then error("Expected 4 digit number got nil") end
	    
	    block1 = "6218"
	    
	    block2 = tostring(math.ceil(math.random() * math.pow(10,8)))
	    for i = #block2, 3 do
			    block2 = block2..i
	    end
	    
	    block3 = tostring(math.ceil(math.random() * math.pow(10,4)))
	    for i = #block3, 3 do
			    block3 = block3..i
	    end
	    
	    return block1.." "..block2.." "..block3.." "..suffix
end

term.clear()
term.setCursorPos(1, 1)

rednet.open("left")

local resumeTimer = os.startTimer(0.1)
local tasks = {}
local x, y

while true do
    event = {os.pullEvent()}
    if event[1] == "rednet_message" then
        if string.match(event[3], "^%[Card%-Request%]") then
            table.insert(tasks, string.match(event[3],"^%[Card%-Request%](.*)"))
        end
    elseif event[1] == "timer" then
        if #tasks > 0 then
            if not disk.isPresent("right") do
                x, y = term.getCursorPos()
                write("Waiting for new 'card'...")
                term.setCursorPos(x, y)
                resumeTimer = os.startTimer(0.1)
            else
                print("\nWriting to card...")
                cardNum = generateRandCardNumber(tasks[1])
                cardNum = generateRandCardNumber(tasks[1])
                disk.setLabel("right", cardNum)
                print("Card number: "..cardNum)
                print("Ejecting card...")
                disk.eject("right")
                print("Card Complete, moving on to next request.")
                table.remove(tasks, 1)
                resumeTimer = os.startTimer(0.1)
            end
        else
            x, y = term.getCursorPos()
            write("Waiting for request...")
            term.setCursorPos(x, y)
            resumeTimer = os.startTimer(0.1)
        end
    end
end

rednet.close("left")

Rednet messages simply arrive on the queue and wait to be pulled like all other events. Since we don't use any calls in this code that eat events (like read(), sleep(), etc.), we don't have to worry about our events disappearing on us while other code runs.
theoriginalbit #11
Posted 14 December 2012 - 05:41 PM
Corrected code; note that I forgot to escape the hyphen the first time.

Nice, works fantastically, thank you :)/> one bug with the if on line 127 tho but its ok I got it ;)/>



if not disk.isPresent("right") do

Rednet messages simply arrive on the queue and wait to be pulled like all other events. Since we don't use any calls in this code that eat events (like read(), sleep(), etc.), we don't have to worry about our events disappearing on us while other code runs.

Ahh ok I was always under the assumption that the pullEvent() also cleared the stack.
Lyqyd #12
Posted 14 December 2012 - 06:41 PM
Oh, just noticed that the card number generation snuck in there twice, so one of those two lines could probably be removed.
theoriginalbit #13
Posted 14 December 2012 - 07:07 PM
Oh, just noticed that the card number generation snuck in there twice, so one of those two lines could probably be removed.

Oh, haha it did too. Doesn't hugely matter anyways, its just a random number.