{"action":"created","issue":{"url":"https://api.github.com/repos/ARMmbed/core-util/issues/58","labels_url":"https://api.github.com/repos/ARMmbed/core-util/issues/58/labels{/name}","comments_url":"https://api.github.com/repos/ARMmbed/core-util/issues/58/comments","events_url":"https://api.github.com/repos/ARMmbed/core-util/issues/58/events","html_url":"https://github.com/ARMmbed/core-util/issues/58","id":127264991,"number":58,"title":"Specialization of all atomic ops","user":{"login":"bremoran","id":2636227,"avatar_url":"https://avatars.githubusercontent.com/u/2636227?v=3","gravatar_id":"","url":"https://api.github.com/users/bremoran","html_url":"https://github.com/bremoran","followers_url":"https://api.github.com/users/bremoran/followers","following_url":"https://api.github.com/users/bremoran/following{/other_user}","gists_url":"https://api.github.com/users/bremoran/gists{/gist_id}","starred_url":"https://api.github.com/users/bremoran/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bremoran/subscriptions","organizations_url":"https://api.github.com/users/bremoran/orgs","repos_url":"https://api.github.com/users/bremoran/repos","events_url":"https://api.github.com/users/bremoran/events{/privacy}","received_events_url":"https://api.github.com/users/bremoran/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/ARMmbed/core-util/labels/mirrored","name":"mirrored","color":"ededed"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":4,"created_at":"2016-01-18T16:42:44Z","updated_at":"2016-01-19T09:14:23Z","closed_at":null,"body":"atomic_incr and atomic_decr could easily be specialized when ```LDREX``` and ```STREX``` are available.  Is this a good idea?\r\n\r\nWhere ```LDREX``` and ```STREX``` are available, the current call path of ```atomic_incr``` is: \r\n\r\n```C++\r\nbool atomic_cas(uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue)\r\n{\r\n    uint32_t currentValue = __LDREXW(ptr);\r\n    if (currentValue != *expectedCurrentValue) {\r\n        *expectedCurrentValue = currentValue;\r\n        __CLREX();\r\n        return false;\r\n    }\r\n\r\n    return !__STREXW(desiredValue, ptr);\r\n}\r\n\r\ntemplate<typename T>\r\nT atomic_incr(T *valuePtr, T delta)\r\n{\r\n    T oldValue = *valuePtr;\r\n    while (true) {\r\n        const T newValue = oldValue + delta;\r\n        if (atomic_cas(valuePtr, &oldValue, newValue)) {\r\n            return newValue;\r\n        }\r\n    }\r\n}\r\n```\r\n\r\nAn alternative implementation is:\r\n\r\n```C++\r\nuint32_t atomic_incr(uint32_t *valuePtr, uint32_t delta)\r\n{\r\n    uint32_t newValue;\r\n    do {\r\n        newValue = __LDREXW(valuePtr) + delta;\r\n    } while (__STREXW(newValue, valuePtr));\r\n    return newValue;\r\n}\r\n```\r\n\r\nThe latter appears to be a more compact, faster, and more readable implementation, but there may be other drawbacks.\r\n\r\ncc @rgrover @bogdanm @0xc0170 @niklas-arm @autopulated "},"comment":{"url":"https://api.github.com/repos/ARMmbed/core-util/issues/comments/172784301","html_url":"https://github.com/ARMmbed/core-util/issues/58#issuecomment-172784301","issue_url":"https://api.github.com/repos/ARMmbed/core-util/issues/58","id":172784301,"user":{"login":"bogdanm","id":211717,"avatar_url":"https://avatars.githubusercontent.com/u/211717?v=3","gravatar_id":"","url":"https://api.github.com/users/bogdanm","html_url":"https://github.com/bogdanm","followers_url":"https://api.github.com/users/bogdanm/followers","following_url":"https://api.github.com/users/bogdanm/following{/other_user}","gists_url":"https://api.github.com/users/bogdanm/gists{/gist_id}","starred_url":"https://api.github.com/users/bogdanm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bogdanm/subscriptions","organizations_url":"https://api.github.com/users/bogdanm/orgs","repos_url":"https://api.github.com/users/bogdanm/repos","events_url":"https://api.github.com/users/bogdanm/events{/privacy}","received_events_url":"https://api.github.com/users/bogdanm/received_events","type":"User","site_admin":false},"created_at":"2016-01-19T09:14:23Z","updated_at":"2016-01-19T09:14:23Z","body":"What Rohit said feels right as a general rule: have a single truly atomic primitive (`atomic_cas` in our case) and implement the rest of atomic operations on top of it. The difference in size between the two versions (above) is also quite suggestive. In the end, I don't believe this is really needed, but if you want to go ahead and implement it, I'm fine with that (but remember to do the same with `atomic_decr` :) )"}}