Lua - Cocoa - String Concat - Simple Table to NSArray - cocoa

Mac OS X 10.5 compatibility, Lua 5.0 compatibility required (hence cannot use current batch of LuaObjc bridges.)
My lua script produces an indexed table containing tens of thousands of strings.
Basic problem: how to concat those strings with a newline separator, to one string, quickly?
Fly in ointment: even using garbage-collection friendly concat code (provided at stackoverflow) the results take far too long for this purpose. (10 seconds vs 1 minute for a brute force solution.)
Proposed solution: offload the job to Cocoa, where it can be done in a fraction of a second, using NSArray's -componentsJoinedByString method.
New fly in ointment: how to get table data from Lua to Cocoa?
The script calls a registered C function, passing it the table. The C function tries to grab the table on the stack:
// Get an NSArray of strings from the first argument on the stack (a table).
NSArray *strings = nsArrayFromIndexedTable(luaState, index_1Based);
...
// Given a simple table consisting of numbers or strings, returns an NSArray.
// Nested subtables are not followed.
NSArray * nsArrayFromIndexedTable(lua_State *L, int argIdx)
{
// (Allegedly) stops GC.
lua_setgcthreshold(L, INT_MAX);
// Arg must be a table.
luaL_checktype(L, argIdx, LUA_TTABLE);
// Get num elements in table, build an array with that many.
int count = luaL_getn(L, 1);
NSMutableArray *array = [NSMutableArray arrayWithCapacity: count];
int i;
for (i = 1; i <= count; i++) {
lua_rawgeti(L, argIdx, i);
int valueType = lua_type(L, -1);
id value = 0x00;
if (valueType is_eq LUA_TNUMBER) {
value = [NSNumber numberWithDouble:lua_tonumber(L, -1)];
} else if (valueType is_eq LUA_TSTRING) {
value = [NSString stringWithUTF8String:lua_tostring(L, -1)];
}
if (value) {
[array addObject:value];
}
}
// Resume GC
lua_setgcthreshold(L, 0); // INTERMITTENT EXC_BAD_ACCESS CRASH HERE!!!!
return array;
}
Problem: calling this function with a (very large) Lua table of strings (intermittently) results in a EXC_BAD_ACCESS.
Debugger results are sporadic; sometimes not providing anything useful, but I've been able to glean that:
If those Lua GC lines included, the crash happens at lua_setgcthreshold, near the end of the function.
But... if those Lua GC lines are commented out, the crash happens at [array addObject:value]
(NSZombieEnabled is on, but is not providing useful info.)
Any help is appreciated.

This:
int count = luaL_getn(L, 1);
Should be:
int count = luaL_getn(L, argIdx);
So you may be getting an incorrect row count and scanning off the end of the table.

Maybe you grow your C stack too much. I am not familiar with Cocoa, but I guess that the Lua values need not be accessible all the time - the string should be copied into NSString. If it is so, try including a lua_pop(L, 1) at the end of the loop, to clean up the C stack and keep it from growing.

Related

Performance drop loop vs iterator

I am using kotlin in combination with lwjgl. So far I had the following code that ran several thousand times per second:
// val textureMap = HashMap<Int, Texture>()
fun bind() {
var index = 0
for(entry in textureMap) {
glActiveTexture(GL_TEXTURE0 + index)
entry.value.bind()
program.setInt(entry.key, index)
++index
}
}
So while this was running absolutely fast and consumed virtually 0 of my frame time as expected I had to replace it because it created an Iterator in every call, eventually leading to tens of thousands of those objects eventually getting garbage collected and halting my program for a few milliseconds which is of course not usable in my application.
So I went ahead and changed it to the following code:
// textures = ArrayList<Texture>()
// indices = ArrayList<Int>()
fun bind() {
var index = 0
while(index < textures.size) {
val uniform = indices[index]
val texture = textures[index]
glActiveTexture(GL_TEXTURE0 + index)
texture.bind()
program.setInt(uniform, index)
++index
}
}
Now for some reason I am noticing a massive drop in performance, namely the function now uses several seconds per frame. Using jvisualvm I was able to determine that all that time is spent in glActiveTexture in the native part as well as the native function in program.setInt(...). I am absolutely stumped why this is the case, especially after comparing the byte code of the two.
This is the decompiled class file for the first (fast) version:
public final void bind()
{
int index = 0;
Map localMap = (Map)this.textureMap;
for (Map.Entry entry : localMap.entrySet())
{
GL13.glActiveTexture(33984 + index);
((Texture)entry.getValue()).bind(); Program
tmp66_63 = this.program;
if (tmp66_63 == null) {
Intrinsics.throwUninitializedPropertyAccessException("program");
}
tmp66_63.setInt(((Number)entry.getKey()).intValue(), index);
index++;
}
}
And that is the byte code of the slow version:
public final void bind()
{
int index = 0;
while (index < this.textures.size())
{
Integer uniform = (Integer)this.indices.get(index);
Texture texture = (Texture)this.textures.get(index);
GL13.glActiveTexture(33984 + index);
texture.bind(); Program
tmp52_49 = this.program;
if (tmp52_49 == null) {
Intrinsics.throwUninitializedPropertyAccessException("program");
}
Integer tmp62_61 = uniform;Intrinsics.checkExpressionValueIsNotNull(tmp62_61, "uniform");tmp52_49.setInt(tmp62_61.intValue(), index);
index++;
}
}
I am extremely confused what is going on here. In both versions the call to glActiveTexture is GL_TEXTURE0 + <an int value>, yet one takes so much more time thatn the other.
Does anyone have an idea what I am missing here?
Basically my entire question can be removed. I should have debugged and not only profiled. The problem was the code that populated the lists, and it didnt remove the old values so the lists grew larger and larger and the loop just ran so many more times over time...
In case anyone was wondering how I fixed my problem with the allocations I essentially created two collections, one is containing the uniforms and one is mapping them to textures. And then I can iterate over the uniforms and then get the respective texture. So no pointless Iterator objects are created but I am also not having any duplicates :)

blocks and the stack

According to bbum:
2) Blocks are created on the stack. Careful.
Consider:
typedef int(^Blocky)(void);
Blocky b[3];
for (int i=0; i<3; i++)
b[i] = ^{ return i;};
for (int i=0; i<3; i++)
printf("b %d\n", b[i]());
You might reasonably expect the above to output:
0
1
2
But, instead, you get:
2
2
2
Since the block is allocated on the stack, the code is nonsense. It
only outputs what it does because the Block created within the lexical
scope of the for() loop’s body hasn’t happened to have been reused for
something else by the compiler.
I don't understand that explanation. If the blocks are created on the stack, then after the for loop completes wouldn't the stack look something like this:
stack:
---------
^{ return i;} #3rd block
^{ return i;} #2nd block
^{ return i;} #1st block
But bbum seems to be saying that when each loop of the for loop completes, the block is popped off the stack; then after the last pop, the 3rd block just happens to be sitting there in unclaimed memory. Then somehow when you call the blocks the pointers all refer to the 3rd block??
You are completely misunderstanding what "on the stack" means.
There is no such thing as a "stack of variables". The "stack" refers to the "call stack", i.e. the stack of call frames. Each call frame stores the current state of the local variables of that function call. All the code in your example is inside a single function, hence there is only one call frame that is relevant here. The "stack" of call frames is not relevant.
The mentioning of "stack" means only that the block is allocated inside the call frame, like local variables. "On the stack" means it has lifetime akin to local variables, i.e. with "automatic storage duration", and its lifetime is scoped to the scope in which it was declared.
This means that the block is not valid after the end of the iteration of the for-loop in which it was created. And the pointer you have to the block now points to an invalid thing, and it is undefined behavior to dereference the pointer. Since the block's lifetime is over and the space it was using is unused, the compiler is free to use that place in the call frame for something else later.
You are lucky that the compiler decided to place a later block in the same place, so that when you try to access the location as a block, it produces a meaningful result. But this is really just undefined behavior. The compiler could, if it wanted, place an integer in part of that space and another variable in another part, and maybe a block in another part of that space, so that when you try to access that location as a block, it will do all sorts of bad things and maybe crash.
The lifetime of the block is exactly analogous to a local variable declared in that same scope. You can see the same result in a simpler example that uses a local variable that reproduces what's going on:
int *b[3];
for (int i=0; i<3; i++) {
int j = i;
b[i] = &j;
}
for (int i=0; i<3; i++)
printf("b %d\n", *b[i]);
prints (probably):
b 2
b 2
b 2
Here, as in the case with the block, you are also storing a pointer to something that is scoped inside the iteration of the loop, and using it after the loop. And again, just because you're lucky, the space for that variable happens to be allocated to the same variable from a later iteration of the loop, so it seems to give a meaningful result, even though it's just undefined behavior.
Now, if you're using ARC, you likely do not see what your quoted text says happening, because ARC requires that when storing something in a variable of block-pointer type (and b[i] has block-pointer type), that a copy is made instead of a retain, and the copy is stored instead. When a stack block is copied, it is moved to the heap (i.e. it is dynamically allocated, and has dynamic lifetime and is memory managed like other objects), and it returns a pointer to the heap block. This you can safely use after the scope.
Yeah, that does make sense, but you really have to think about it. When b[0] is given its value, the "^{ return 0;}" is never used again. b[0] is just the address of it. The compiler kept overwriting those temp functions on the stack as it went along, so the "2" is just the last function written in that space. If you print those 3 addresses as they are created, I bet they are all the same.
On the other hand, if you unroll your assignment loop, and add other references to "^{ return 0;}", like assigning it to a c[0], and you'll likely see b[0] != b[1] != b[2]:
b[0] = ^{ return 0;};
b[1] = ^{ return 1;};
b[2] = ^{ return 2;};
c[0] = ^{ return 0;};
c[1] = ^{ return 1;};
c[2] = ^{ return 2;};
Optimization settings could affect the outcome.
By the way, I don't think bbum is saying the pop happens after the for loop completion -- it's happening after each iteration hits that closing brace (end of scope).
Mike Ash provides the answer:
Block objects [which are allocated on the stack] are only valid through the lifetime of their
enclosing scope
In bbum's example, the scope of the block is the for-loop's enclosing braces(which bbum omitted):
for (int i=0; i<3; i++) {#<------
b[i] = ^{ return i;};
}#<-----
So, each time through the loop, the newly created block is pushed onto the stack; then when each loop ends, the block is popped off the stack.
If you print those 3 addresses as they are created, I bet they are all
the same.
Yes, I think that's the way that it must have worked in the past. However, now it appears that a loop does not cause the block to be popped off the stack. Now, it must be the method's braces that determine the block's enclosing scope. Edit: Nope. I constructed an experiment, and I still get different addresses for each block:
AppDelegate.h:
typedef int(^Blocky)(void); #******TYPEDEF HERE********
#interface AppDelegate : NSObject <NSApplicationDelegate>
#end
AppDelegate.m:
#import "AppDelegate.h"
#interface AppDelegate ()
-(Blocky)blockTest:(int)i {
Blocky myBlock = ^{return i;}; #If the block is allocated on the stack, it should be popped off the stack at the end of this method.
NSLog(#"%p", myBlock);
return myBlock;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
Blocky b[3];
for (int i=0; i < 3; ++i) {
b[i] = [self blockTest:i];
}
for (int j=0; j < 3; ++j) {
NSLog(#"%d", b[j]() );
}
}
#end
--output:--
0x608000051820
0x608000051850
0x6080000517c0
0
1
2
That looks to me like blocks are allocated on the heap.
Okay, my results above are due to ARC. If I turn off ARC, then I get different results:
0x7fff5fbfe658
0x7fff5fbfe658
0x7fff5fbfe658
2
1606411952
1606411952
That looks like stack allocation. Each pointer points to the same area of memory because after a block is popped off the stack, that area of memory is reused for the next block.
Then it looks like when the first block was called it just happened to get the correct result, but by the time the 2nd block was called, the system had overwritten the reclaimed memory resulting in a junk value? I'm still not clear on how calling a non-existent block results in a value??

Add CCNodes to a Parent CCNode using a for loop

-(CCNode *)createFieldNode:(NSMutableArray *)fieldArray{
CGSize winSize = [CCDirector sharedDirector].viewSize;
CCNode* stackNode= [CCNode node];
for (int i; i <=fieldArray.count; i++){
//itemP is previous item in array and itemC is current item in area based on index i
BPItem*itemP;
BPItem*itemC;
if(i!=0){
itemP=[fieldArray objectAtIndex:i-1];
itemC=[fieldArray objectAtIndex:i];
float stackWidth=arc4random()%200+50;
float stackHeight=itemP.position.y+itemP.contentSize.height;
itemC.position=ccp(stackWidth,stackHeight);
}
else{
itemC=[fieldArray objectAtIndex:i];
float stackWidth=arc4random()%200+50;
itemC.position=ccp(stackWidth,0);
}
//having trouble adding multiple nodes to stackNode
[stackNode addChild:itemC];
}
return stackNode;
}
I want to add CCNodes from fieldArray on to a parent CCNode "stackNode". When I use breakpoints I am able to add the CCNode at index 0 and CCNode at index 1. However the program crash at i=2. The error I receive is:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'child already added to another node. It can't be added again'
Before the crash "stackNode" has two children. I'm not adding the CCNodes one by one because I have hundreds of different arrays with many a fieldArray.count around 20. Please help I can explain more if I have been unclear.
Change the for loop start as follows :
//itemP is previous item in array and itemC is current item in area based on index i
BPItem*itemP;
BPItem*itemC; // moved out of the for loop
for (int i; i <fieldArray.count; i++){ // <- changed the end condition to avoid crash
... rest of loop
Also, in the code that creates fieldArray, make certain you have logic to ensure that there are no duplicates, otherwise you will have the same issue (but for an altogether different reason).

controlling an AudioUnit with MIDI keyboard OSX

I'd like to learn if a simple CoreAudio component (of subtype kAudioUnitSubType_HALOutput, e.g.), can be parametrically controlled by a MIDI keyboard, let's say MIDI note number be translated into interpollating oscillator frequency? On the other hand, controlling such a parameter by means of a GUI element works like a dream.
I found no single example of such a code on the entire web.
I don't need SinSynth, Sampler, MusicDevice, SoundFonts, Midi files, GM, ADSRs, plug-in level of functionality, etc.
Just need a plain piece of information or hint on how can data from a MIDI packet read by means of a midiReadProc get passed to a audio render callback, much like values of a slider can. With MIDI there seems to be a threading issue, I found no documentation about.
I'd prefer to do it in CoreAudio API, if possible, I'm sure it must be.
On the other hand, using Apple pre-built music instrument devices would lead me into a completely wrong direction.
Thanks in advance,
CA
It seems you want to controls some of parameters or properties of AudioUnit using MIDI-keyboard. In this case all that you need is take MIDIPacket's data field.
What every byte mean you can look here.
After that, depending on value of needed byte, you need to set property or parameter value.
Here's a minimalistic answer to the question that I've learned and made work meanwhile. It's a matter of making a midiReadProc generate values which an audioRenderProc can accept as parameters. Please note that this works in stand-alone apps. For writing AU-plug-ins I recommend understanding and using CoreAudioUtilityClasses, as provided by Apple.
A simplest example of createMidi in C:
//these have to be declared somewhere
MIDIClientRef midiclient;
MIDIPortRef midiin;
void createMIDI (void)
{
//create MIDI input and client - - - - - - - - - - -
midiclient = 0;
CheckError(MIDIClientCreate(CFSTR("MIDI_Client"),
NULL,
/*midiClientNotifyRefCon*/NULL,
&midiclient),
"MIDI Client Create Error\n");
CheckError(MIDIInputPortCreate(midiclient,
CFSTR("MIDI_Input"),
midiReadProc,
NULL,
&midiin),
"MIDI Port Create Error\n");
//connect MIDI - - - - - - - - - - - - - - - - - - -
ItemCount mSrcs = MIDIGetNumberOfSources();
printf("MIDI Sources: %ld\n", (long)mSrcs);
ItemCount iSrc;
for (iSrc=0; iSrc<mSrcs; iSrc++) {
MIDIEndpointRef src = MIDIGetSource(iSrc);
MIDIPortConnectSource(midiin, src, NULL);
}
}
CheckError( ) is a generic utility function modeled after "Learning Core Audio", by C.Adamson & K.Avila, ISBN 0-321-63684-8...
...and a plain-C midiReadProc template. Please note that many manufacturers of MIDI hardware don't implement the standardized noteOff event, but rather a "hacked" version consisting of a zero-velocity-noteOn, due to alleged improving MIDI-latency issues, but they hardly document it. So, one has to check against both scenarios:
void midiReadProc(const MIDIPacketList *packetList,
void* readProcRefCon,
void* srcConnRefCon)
{
Byte note;
Byte velocity;
MIDIPacket *packet = (MIDIPacket*)packetList->packet;
int count = packetList->numPackets;
for (int k=0; k < count; k++) {
Byte midiStatus = packet->data[0];
Byte midiChannel = midiStatus & 0x0F;
Byte midiCommand = midiStatus >> 4;
if ((midiCommand == 0x08)||(midiCommand == 0x09)){
if(midiCommand == 0x09){
note = packet->data[1] & 0x7F;
velocity = packet->data[2] & 0x7F;
if (velocity == 0x0){ //"hacked" note-off
; //do something
}else{//note on
; //do something
}
}
if(midiCommand == 0x08){ //proper note-off
;//do something
}
}else{
;//do something else
}
packet = MIDIPacketNext(packet);
}//end for (k = 0; ...;...)
}
Everything else is a matter of common good programing practice.

Retain a random number across different functions in Cocoa?

I know how to do a global variable, but whenever I try to define a global variable with a random number function, xcode says "initializer element is not constant." The compiler doesn't want to make a variable from a random number because the random number function is not constant.
How do I generate a random number and then use that same value for more than one action? (For example, to define a color and then write that value to a label?)
Code:
#import "Slider_with_IBAppDelegate.h"
float * const hue = ((arc4random() % ((unsigned)100 + 1))/100.0);
//^this is where I get the error: "initializer element is not constant"
#synthesize label
//write value to label
- (IBAction) doButton {
label.text = [NSString stringWithFormat:#"%f", hue];
}
//set background color
- (void)applicationDidBecomeActive:(UIApplication*)application
{
self.label5.backgroundColor = [UIColor colorWithHue:hue
saturation:1.0
brightness:1.0
alpha:1.0];
}
----edit------
Thanks for the suggestions. It still doesn't work for me, though, what am I doing wrong?
New code:
#import "Slider_with_IBAppDelegate.h"
float const hue = ((arc4random() % ((unsigned)100 + 1))/100.0);
//^I still get the error: "initializer element is not constant."
#synthesize label
//write value to label
- (IBAction) doButton {
label.text = [NSString stringWithFormat:#"%f", hue];
}
//^this is where I get the error "'hue' undeclared (first use of this function)"
//set background color
- (void)applicationDidBecomeActive:(UIApplication*)application
{
hue = ((arc4random() % ((unsigned)1000 + 1))/1000.0);
/*here I get the error "assignment of read-only variable 'hue.'"
If I insert "float" just before hue, I do not get this error,
but it still won't compile because of the error above.*/
self.label5.backgroundColor = [UIColor colorWithHue:hue
saturation:1.0
brightness:1.0
alpha:1.0];
}
Make it non-const and initialize it in applicationDidBecomeActive. Is there a reason it must be constant?
I know how to do a global variable, but whenever I try to define a global variable with a random number function, xcode says "incompatible types in initialization."
float * const hue = ((arc4random() % ((unsigned)100 + 1))/100.0);
That's not a function; it's an expression. I'd be surprised if you're not also getting an error here, because you can't initialize a global variable with an expression that isn't constant. As alltom.com says, you need to assign to it from applicationDidBecomeActive:.
The warning is because you've given the variable a pointer type (float *), but you're not assigning a pointer to it. Cut out the asterisk, because you're not going to put a pointer in this variable.
Xcode doesn't want to make a variable from a random number because the random number function is not constant.
Xcode doesn't care one way or the other. It's just reporting the findings of the compiler. By default, the compiler for Objective-C is GCC, but Xcode supports other compilers (and Xcode does come with one other C/Objective-C compiler: LLVM-GCC).
… I couldn't call the same value for the label.
You're not showing a label here, and you can't call a value. You can only call a function, and you don't have one in the code shown.
It gave me the error "function undefined: first use of this function" in doButton even though it was defined in applicationDidBecomeActive.
No, it wasn't. Assigning to a variable does not create a function.
In case anyone is wondering, I finally found a way to do this effectively. (I am sure this is what alltom was saying, I was just too dumb to understand.)
I declared a float and a seed in my .h file:
- (float)generate:(id)sender;
- (void)seed;
And in the implementation file, I defined the float as a random number, and I used srandom() as a random seed generator.
- (float)generate:(id)sender
{
//Generate a number between 1 and 100 inclusive
int generated;
generated = (random() % 100) + 1;
return(generated);
}
- (void)seed {
srandom(time(NULL));
}
Then anywhere I wanted to retain a random number, I used
srandom(time(NULL));
generated1 = ((random() % 100) + 1)/100.0;
to initiate the number, and from there I was able to use generated1, generated2, hue, etc. as variables in any function I wanted (and I made sure to declare these variables as floats at the top of the file).

Resources