Jump to content
  • Advertisement

hiago desena

  • Content Count

  • Joined

  • Last visited

Community Reputation

0 Neutral

About hiago desena

  • Rank

Personal Information

  • Role
  • Interests

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Thanks for the fix @WitchLord. Btw now for this to work you cant have the baseclass in angelscript side be ABSTRACT. You cant overwrite opAssign for abstract class because the class cant be instantiated and thus angelscript cant copy. For example: FSMState@ opAssign(const FSMState &in other) if FSMState is an abstract angelscript class this opAssign wont work, should mention that in the docs. Thanks!
  2. In addition to this issue, i have found another problematic issue with the "inherit from registered class type" example. The issue stems from the fact that in the proxy class you are holding a weak reference to the scriptObject that gets passed in during the factory construction, in addition of storing a pointer to that scriptobject class. Proxy(asIScriptObject* instance). The "instance" is the script object that gets passed in when the object is constructed. When angelscript goes to asIScriptObject::operator= (Presumed that the current crash we talked about is not happening) it will try to copy each property. In the case of the Proxy@ property we just assign the handles by AddRef one and Release the other. Now the new object holds a new handle (Proxy@), BUT BUT that proxy handle holds a Weak Ptr and asIScriptObject* to the old object still. The one that it was created with during construction. So the next time you AddRef/Release it will perform the action to the wrong desired object that should be out of scope. I think you can fix issue by not having the proxy class hold an object handle. But instead just have it instantiate the proxy and then have the c++ implementent an operator=. In the operator= implementation you would need to assign the new 'rhs' asIScriptObject* so that it matches with the proxy. In addition, I have bypassed the crash in operator= by adding two new functions to the proxy class. bool AddRefScriptObject(void) const; bool ReleasecriptObject(void) const; These functions manually AddRef/Release the underlying script object if the c++ side wants to hold a strong reference to them. This means that the proxy class would not by default attempt to add/ref the underlying script object. Which removed unwanted behavior of the script object owned by angelscript getting nuked where it shouldnt. Thanks, Hope this gives you more information 😃
  3. Hi @WitchLord. I dont think the change your suggesting would fix the issue. The main problem is the fact that in your "inherit from a registered class example" in the AddRef you addref the objectInstance and vice versa in the Release. So that means whenever a copy handle gets copied using the asIScriptObject::CopyHandle(), your going to need to release the 'this' instance as some point. Before or after the old one, but the old one is the 'this' one. Since you are releasing the property proxy, it will release the script object instance and force a nuke of the 'this' script object. When it returns from the callstack it will crash no matter what order you release. Maybe you might be seeing something im not seeing? I tried implementing the suggested change locally but no luck.
  4. Hi i ran into a little problem related to when i want to inherit from a registered class using the mechanism explained here: https://www.angelcode.com/angelscript/sdk/docs/manual/doc_adv_inheritappclass.html // Angelscript side shared abstract class FSMState { private FSMStateProxy@ instance; FSMState() { @instance = FSMStateProxy(); } void Enter(void) {} void Exit(void) {} void AddAction(const Variant& in action) { instance.AddAction(action); } void RemoveAction(const StringHash &in actionID) { instance.RemoveAction(actionID); } } class PlayerMoveState : FSMState { PlayerMoveState() { Printf("Hi"); } } // function logic thats uses classes { PlayerMoveState moveState; controller.AddState(moveState); } /////////////////////////////////////////////// C++ side .cpp /////////////////////////////////////////////// ScriptProxyRefCountedObject::ScriptProxyRefCountedObject(asIScriptObject* object) : GTL::RefCountedObject() , m_objectInstance(object) , m_bIsDead(object->GetWeakRefFlag()) { // increment weak ref as we want to hold a reference to the object m_bIsDead->AddRef(); // note: internal counter starts of with (1) for script objects RefCountedObject::AddRef(); CHECK(m_objectInstance && m_bIsDead); } ScriptProxyRefCountedObject::~ScriptProxyRefCountedObject() { m_bIsDead->Release(); } // add/release for managing object unsigned ScriptProxyRefCountedObject::AddRef(void) const { // increment angelscript side counter as well to made sure it doest not get destroyed // before the c++ side if (!m_bIsDead->Get()) m_objectInstance->AddRef(); return GTL::RefCountedObject::AddRef(); } unsigned ScriptProxyRefCountedObject::Release(void) const { // release angelscript instance as well if (!m_bIsDead->Get()) m_objectInstance->Release(); return GTL::RefCountedObject::Release(); } } The problem stems when "controller.AddState()" gets called because. Since Add state executes a copy of the object. It has to create a second instance and invoke the ScriptObject::operator= for each property within the script object. So we have CopyA: ScriptObject::RefCount = 1 Proxy::WeakRef=2 Proxy::m_objectInstance = 1 where (Proxy::m_objectInstance == ScriptObject::RefCount) CopyB: ScriptObject::RefCount = 1 Proxy::WeakRef=2 Proxy::m_objectInstance = 1 where (Proxy::m_objectInstance == ScriptObject::RefCount) When the script object invokes the operator= it will invoke the CopyHandle function and perform a Release on the destination handle and then an add-ref on the source handle. Then assigns the new handle. The problem is that for any proxy thats hits this operator= with both instance at a ref-count = 1. Then the release call in the CopyHandle will invoke CopyA::ScriptProxyRefCountedObject::Release, invoking m_objectInstance->Release() and thus Destroying the whole scriptObject. Destroying the script object will force the same CopyA::m_objectInstance->Release() function be called in the destructor. When the logic finishes invoking and goes back up to the operator= call stack, then we crash as 'this' pointer aka the object that was destroyed got nuked. Hope that explains my problem. Hoping @WitchLord can help or elaborate on something im missing with regards to the example shown in the docs. This crash should happen given the example code below which is given in the angelscript documentation and i just added an additional function. void TestFunction(FooDerived &in CopyA) { } void main() { // When newly created the m_value is 0 FooDerived d; assert( d.m_value == 0 ); // invoking this function should force a copy to be created and the asIScriptObject::operator= to be called // where internal ref-count of the object stored in the proxy are both = 1. Crash occurs TestFunction(d); // When calling the method the m_value is incremented with 1 d.CallMe(); assert( d.m_value == 1 ); } please let me know if im missing something in regards on how to property handle proxy inheritance.
  5. hiago desena

    Building scripts in multiple-threads.

    Im curious to know if you have any current plays to implement being able to compile/Build threads from multiple-threads. In comment you say it is 'possible' curious if u had any plans on implementing it any time soon?
  6. hiago desena

    Script classes nested GetAdressOfProperty

    I thought i was clear. Im sorry this is better: Class B { int IntValue; float FloatValue; } class A { B mValue; } Where class A has a instance of B instead of it that is NOT a pointer, but is by value. The issue is that both these classes within a script are defined solely on angelscript side so in C++ im only working with the void* to the address.
  7. I couldnt find any example of this so im wondering if you support in angelscript. So the scenerio is that I have these two script classes. Class B { int IntValue; float FloatValue; } class A { class B; } So class "A" is my scriptObject that i then perform the GetPropertyCount. I iterate through each property (There is only one) And I do GetAddressOfProperty which returns me a void* to class "B". Now i have the type information for class B, so I then want to iterate through each property information for class "B". Is there a way through the API for me to access the address of that "A.B.IntValue". ?? If you have any questions let me know
  8. hiago desena

    Multi-threading race condition

    Thank you. Im dumb. Because I didnt build in the project with Multi-threading support ON the thread local data GetLocalData for each context for returning the single main thread-data. Thanks again. With a follow up question. I know angelscript works with Xbox One + PS4. Does this include multi-threading support for those platform as well. In addition have u tested for the Nitendo-Switch platform for portability.
  9. hiago desena

    Multi-threading race condition

    After some digging. I got the crash to stop happening. Im dumb. The fix was to build angelscript with AS_NO_THREADS turned off and enabling locking mechanisms. Though this fixed my issue, still begs the question why locking the pushing and popping to that thread-local data is not needed.
  10. hiago desena

    Multi-threading race condition

    In your documentation in the "Thing to think about in multithreading" you state: Multiple threads may execute scripts in separate contexts. The contexts may execute scripts from the same module, but if the module has global variables you need to make sure the scripts perform proper access control so that they do not get corrupted, if multiple threads try to update them simultaneously. So with that said in the scenario where i have 1 engine created. with 2 threads alive. Now each thread is designated its own personal context-pool. Now note: Each allocate script-class instance assigned to a specific thread and will always run on that thread. aka a script instances executing in thread 0 can not access/talk/write with another script instances executing in thread 1. Now the issue comes with this asCThreadLocalData when a context execute a function. When the context executes a function it will access the threadlocaldata and attempt to push the active stack on to the thread shared memory (memory of the thread that allocated the engine, which there is one). Then it follows with a pop when unprepare is called. As you can see this pushing/popping on the thread local data is not safe ( which makes sense since its called thread-local data, 1-per engine). But that would mean that you cant ever invoke two script classes member functions using 2 different context from 2 different thread simultaneously as it will end up (at some point). Hitting the assert: as_context.cpp line 173 asASSERT(tld && tld->activeContexts[tld->activeContexts.GetLength() - 1] == ctx); Now the fix for me obivously is since each thread is independent (aka any script classess assigned to a thread will always run on that thread) I can just create an engine per-group of thread and then the shared-local memory would be one per-thread. (Since they dont/cant communicate with each other anyways, but that seems bloated). Im wondering if you can paint me a picture that clarifies the "Multiple threads may execute scripts in separate contexts.". Should i implement my own thread manager? (Looking into this now) Thanks!
  11. So I have two scripts that are loaded into two different modules. Module A and Module B. Each module defines a single shared script-class. Now when i start the application, create each module and build them everything is a success, but if i change the script-code with random letters to cause an error and then force a rebuild of the script (so i know it should fail as I myself inserted a compile-syntax error). I check the string buffer of the contents and its all there but when module->Build() it returns 0 aka a success. This only happens when i shared defined in all my classes for script-classes. Any ideas anyone? More Info: If the script class has a function called void Stop() { } if I remove one of the curly brance to force a recompile, then it works with shared class instantiantion. But if I force something like this void Stop() { adadadkf[kgfaflaff; } Where that "adadadkf[kgfaflaff;" is clearly a syntax error then the build() call wont yell at me for some reason. Note: If i relaunch the application for the first time the script is called and that garabage is defined then it will yell at me but once the script is compiled, it stopped picking up syntax-error inside functions. Do i need to rebuild as scripts that are shared or something? Any ideas?
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!