summaryrefslogtreecommitdiff
path: root/src/tests/eo/suite
diff options
context:
space:
mode:
authorJean-Philippe Andre <jp.andre@samsung.com>2017-10-13 17:18:41 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2017-10-18 11:02:16 +0900
commitdf304d0155a5f1005798a783b3f8b00cef07f753 (patch)
treee02ce68ccad635e79e99db25117853b9a4c1f7bc /src/tests/eo/suite
parenta1a04629e417773772ea407f9abc456bb90f05f4 (diff)
eo: Add beta API for auto_unref after a call
Before screaming in horror (C++...) here's why we may need this: Efl.Part.part API returns an object that is by definition valid for a single function call only. Enforcing this in practice is actually quite hard as all implementation functions must manually take care of the life-cycle. This is a lot of code in many places and a lot of opportunities to forget to properly handle that life-cycle. Also, this means any invalid function call on a part will leak an object. This API absolutely must remain either "internal" or "beta" and definitely not become abused by applications. On top of that such an API can cause great trouble for bindings like C++. As a consequence, only specially crafted APIs like efl_part() should return an object marked as auto_unref. Alternatively this API could be defined in Eo.h or some other Eo_Internal.h. I placed it in efl_object.eo because it's much more convenient :) (read: I'm lazy) **** Performance notes: Tested with clang & gcc (with -O2), I had a look at the output of perf top, in particular the asm view. I used eo_bench in a loop. My conclusions are: - EINA_LIKELY/UNLIKELY actually works. The jump statement varies according to the expectation. I highly doubt all those ugly goto in eo.c / Eo.h are even useful. - The impact of auto_unref on a call_resolve is so small it doesn't even appear in the trace. It is significant inside call_end, though (obviously, that function is just a few lines long). That function accounts for ~1% to ~4% of all CPU time. The impact of auto_unref in call_end is ~4% of the function time. This means ~0.16% of all CPU time (worst measured case). _efl_object_op_api_id_get simply doesn't show up because of caching, so the extra check there is negligible. PS: I also tested EINA_LIKELY/UNLIKELY by compiling with -O2 and looking at the output with objdump. The flag is well respected, and the jump instructions are what you would expect (no jump for LIKELY and jump for UNLIKELY). Conclusion: The goto's in eo.c only make the code harder to read...
Diffstat (limited to 'src/tests/eo/suite')
-rw-r--r--src/tests/eo/suite/eo_test_general.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/src/tests/eo/suite/eo_test_general.c b/src/tests/eo/suite/eo_test_general.c
index 9a26ffea42..3c21e71c14 100644
--- a/src/tests/eo/suite/eo_test_general.c
+++ b/src/tests/eo/suite/eo_test_general.c
@@ -9,6 +9,9 @@
9# include <unistd.h> 9# include <unistd.h>
10#endif 10#endif
11 11
12#define EFL_OBJECT_BETA
13#define EFL_OBJECT_PROTECTED
14
12#include <Eo.h> 15#include <Eo.h>
13 16
14#include "eo_suite.h" 17#include "eo_suite.h"
@@ -1719,6 +1722,59 @@ START_TEST(efl_cast_test)
1719} 1722}
1720END_TEST 1723END_TEST
1721 1724
1725static void
1726_auto_unref_del_cb(void *data, const Efl_Event *ev EINA_UNUSED)
1727{
1728 *((int *) data) = 1;
1729}
1730
1731START_TEST(efl_object_auto_unref_test)
1732{
1733 int _auto_unref_del;
1734 Eo *obj, *parent;
1735
1736 efl_object_init();
1737
1738 // Test unref after valid call
1739 _auto_unref_del = 0;
1740 obj = efl_add(SIMPLE_CLASS, NULL);
1741 fail_if(efl_ref_get(obj) != 1);
1742 efl_event_callback_add(obj, EFL_EVENT_DEL, _auto_unref_del_cb, &_auto_unref_del);
1743 efl_auto_unref_set(obj, 1);
1744 fail_if(_auto_unref_del);
1745 fail_if(efl_ref_get(obj) != 1);
1746 efl_name_set(obj, "name");
1747 fail_if(!_auto_unref_del);
1748
1749 // Test unref after invalid call
1750 _auto_unref_del = 0;
1751 obj = efl_add(SIMPLE_CLASS, NULL);
1752 fail_if(efl_ref_get(obj) != 1);
1753 efl_event_callback_add(obj, EFL_EVENT_DEL, _auto_unref_del_cb, &_auto_unref_del);
1754 efl_auto_unref_set(obj, 1);
1755 fail_if(_auto_unref_del);
1756 fail_if(efl_ref_get(obj) != 1);
1757 simple_no_implementation(obj);
1758 fail_if(!_auto_unref_del);
1759
1760 // Same with a parent
1761 _auto_unref_del = 0;
1762 parent = efl_add(SIMPLE_CLASS, NULL);
1763 obj = efl_add(SIMPLE_CLASS, parent);
1764 fail_if(efl_ref_get(obj) != 1);
1765 efl_allow_parent_unref_set(obj, 1);
1766 efl_event_callback_add(obj, EFL_EVENT_DEL, _auto_unref_del_cb, &_auto_unref_del);
1767 efl_auto_unref_set(obj, 1);
1768 fail_if(_auto_unref_del);
1769 fail_if(efl_ref_get(obj) != 1);
1770 efl_name_set(obj, "name");
1771 fail_if(!_auto_unref_del);
1772 efl_del(parent);
1773
1774 efl_object_shutdown();
1775}
1776END_TEST
1777
1722void eo_test_general(TCase *tc) 1778void eo_test_general(TCase *tc)
1723{ 1779{
1724 tcase_add_test(tc, eo_simple); 1780 tcase_add_test(tc, eo_simple);
@@ -1744,4 +1800,5 @@ void eo_test_general(TCase *tc)
1744 tcase_add_test(tc, eo_rec_interface); 1800 tcase_add_test(tc, eo_rec_interface);
1745 tcase_add_test(tc, eo_domain); 1801 tcase_add_test(tc, eo_domain);
1746 tcase_add_test(tc, efl_cast_test); 1802 tcase_add_test(tc, efl_cast_test);
1803 tcase_add_test(tc, efl_object_auto_unref_test);
1747} 1804}