#include <iostream> #include <memory> #include <string> class AutoTimer { public: explicit AutoTimer(const std::string &name); ~AutoTimer(); void ConstMember() const; void NonConstMember(); private: class Impl; std::shared_ptr<Impl> GetImpl() { return mImpl; } std::shared_ptr<const Impl> GetConstImpl() const { return mImpl; } std::shared_ptr<Impl> mImpl; }; class AutoTimer::Impl { public: double GetElapsed() const { return 0.0; } std::string mName; void ConstMember() const {} void NonConstMember() {} }; AutoTimer::AutoTimer(const std::string &name) : mImpl(new AutoTimer::Impl()) { mImpl->mName = name; } AutoTimer::~AutoTimer() { std::cout << mImpl->mName << ": took " << mImpl->GetElapsed() << " secs" << std::endl; } void AutoTimer::ConstMember() const { GetConstImpl()->ConstMember(); } void AutoTimer::NonConstMember() { GetImpl()->NonConstMember(); } #include <iostream> #include <memory> class MyObject { public: MyObject() { std::cout << "+++ Object created" << std::endl; } ~MyObject() { std::cout << "--- Object destroyed" << std::endl; } }; class MyObjectHolder { public: MyObjectHolder() : obj(std::make_shared<MyObject>()) {} ~MyObjectHolder() = default; private: std::shared_ptr<MyObject> obj; }; int main(int argc, const char * argv[]) { std::cout << "Shared Pointer - START" << std::endl; { std::shared_ptr<MyObject> obj1 = std::make_shared<MyObject>(); { std::shared_ptr<MyObject> obj2 = obj1; // ref count == 2 } // obj2 goes out of scope, ref count == 1 } // obj1 goes out of scope, ref count == 0, object deleted std::cout << "Shared Pointer - END" << std::endl; std::cout << "Unique Pointer - START" << std::endl; { MyObjectHolder objHolder; MyObjectHolder objHolder2 = objHolder; std::cout << "Created MyObjectHolder" << std::endl; } std::cout << "Unique Pointer - END" << std::endl; return 0; } #include <iostream> class Observable { public: virtual ~Observable() {} virtual void CallbackMethod(const std::string &name) = 0; }; class MyObserver: public Observable { public: MyObserver(int data) : mData(data) {} void CallbackMethod(const std::string &name) { std::cout << "Invoking callable " << name << ": " << mData << " "; } private: int mData; }; class ModuleB { public: void SetObserver(std::shared_ptr<Observable> cb) { mObserver = cb; } void InvokeObserver(const std::string &name) { if (mObserver) { mObserver->CallbackMethod(name); } } private: std::shared_ptr<Observable> mObserver; }; int main(int argc, const char * argv[]) { ModuleB b; b.SetObserver(std::make_shared<MyObserver>(2)); b.InvokeObserver("hello"); return 0; } #include <iostream> #include <memory> #include <string> class AutoTimer { public: explicit AutoTimer(const std::string &name); ~AutoTimer(); void ConstMember() const; void NonConstMember(); private: class Impl; std::shared_ptr<Impl> GetImpl() { return mImpl; } std::shared_ptr<const Impl> GetConstImpl() const { return mImpl; } std::shared_ptr<Impl> mImpl; }; class AutoTimer::Impl { public: double GetElapsed() const { return 0.0; } std::string mName; void ConstMember() const {} void NonConstMember() {} }; AutoTimer::AutoTimer(const std::string &name) : mImpl(new AutoTimer::Impl()) { mImpl->mName = name; } AutoTimer::~AutoTimer() { std::cout << mImpl->mName << ": took " << mImpl->GetElapsed() << " secs" << std::endl; } void AutoTimer::ConstMember() const { GetConstImpl()->ConstMember(); } void AutoTimer::NonConstMember() { GetImpl()->NonConstMember(); } #include <iostream> #include <memory> class MyObject { public: MyObject() { std::cout << "+++ Object created" << std::endl; } ~MyObject() { std::cout << "--- Object destroyed" << std::endl; } }; class MyObjectHolder { public: MyObjectHolder() : obj(std::make_shared<MyObject>()) {} ~MyObjectHolder() = default; private: std::shared_ptr<MyObject> obj; }; int main(int argc, const char * argv[]) { std::cout << "Shared Pointer - START" << std::endl; { std::shared_ptr<MyObject> obj1 = std::make_shared<MyObject>(); { std::shared_ptr<MyObject> obj2 = obj1; // ref count == 2 } // obj2 goes out of scope, ref count == 1 } // obj1 goes out of scope, ref count == 0, object deleted std::cout << "Shared Pointer - END" << std::endl; std::cout << "Unique Pointer - START" << std::endl; { MyObjectHolder objHolder; MyObjectHolder objHolder2 = objHolder; std::cout << "Created MyObjectHolder" << std::endl; } std::cout << "Unique Pointer - END" << std::endl; return 0; } #include <iostream> class Observable { public: virtual ~Observable() {} virtual void CallbackMethod(const std::string &name) = 0; }; class MyObserver: public Observable { public: MyObserver(int data) : mData(data) {} void CallbackMethod(const std::string &name) { std::cout << "Invoking callable " << name << ": " << mData << " "; } private: int mData; }; class ModuleB { public: void SetObserver(std::shared_ptr<Observable> cb) { mObserver = cb; } void InvokeObserver(const std::string &name) { if (mObserver) { mObserver->CallbackMethod(name); } } private: std::shared_ptr<Observable> mObserver; }; int main(int argc, const char * argv[]) { ModuleB b; b.SetObserver(std::make_shared<MyObserver>(2)); b.InvokeObserver("hello"); return 0; } #include <iostream> #include <memory> #include <string> class AutoTimer { public: explicit AutoTimer(const std::string &name); ~AutoTimer(); void ConstMember() const; void NonConstMember(); private: class Impl; std::shared_ptr<Impl> GetImpl() { return mImpl; } std::shared_ptr<const Impl> GetConstImpl() const { return mImpl; } std::shared_ptr<Impl> mImpl; }; class AutoTimer::Impl { public: double GetElapsed() const { return 0.0; } std::string mName; void ConstMember() const {} void NonConstMember() {} }; AutoTimer::AutoTimer(const std::string &name) : mImpl(new AutoTimer::Impl()) { mImpl->mName = name; } AutoTimer::~AutoTimer() { std::cout << mImpl->mName << ": took " << mImpl->GetElapsed() << " secs" << std::endl; } void AutoTimer::ConstMember() const { GetConstImpl()->ConstMember(); } void AutoTimer::NonConstMember() { GetImpl()->NonConstMember(); } #include <iostream> #include <memory> class MyObject { public: MyObject() { std::cout << "+++ Object created" << std::endl; } ~MyObject() { std::cout << "--- Object destroyed" << std::endl; } }; class MyObjectHolder { public: MyObjectHolder() : obj(std::make_shared<MyObject>()) {} ~MyObjectHolder() = default; private: std::shared_ptr<MyObject> obj; }; int main(int argc, const char * argv[]) { std::cout << "Shared Pointer - START" << std::endl; { std::shared_ptr<MyObject> obj1 = std::make_shared<MyObject>(); { std::shared_ptr<MyObject> obj2 = obj1; // ref count == 2 } // obj2 goes out of scope, ref count == 1 } // obj1 goes out of scope, ref count == 0, object deleted std::cout << "Shared Pointer - END" << std::endl; std::cout << "Unique Pointer - START" << std::endl; { MyObjectHolder objHolder; MyObjectHolder objHolder2 = objHolder; std::cout << "Created MyObjectHolder" << std::endl; } std::cout << "Unique Pointer - END" << std::endl; return 0; } #include <iostream> class Observable { public: virtual ~Observable() {} virtual void CallbackMethod(const std::string &name) = 0; }; class MyObserver: public Observable { public: MyObserver(int data) : mData(data) {} void CallbackMethod(const std::string &name) { std::cout << "Invoking callable " << name << ": " << mData << " "; } private: int mData; }; class ModuleB { public: void SetObserver(std::shared_ptr<Observable> cb) { mObserver = cb; } void InvokeObserver(const std::string &name) { if (mObserver) { mObserver->CallbackMethod(name); } } private: std::shared_ptr<Observable> mObserver; }; int main(int argc, const char * argv[]) { ModuleB b; b.SetObserver(std::make_shared<MyObserver>(2)); b.InvokeObserver("hello"); return 0; }
Martin Reddy
Software Architect
AI / Web / 3D
I am a seasoned software engineering leader, book author, and serial entrepreneur. I hold a Ph.D. in Computer Science, am a Fellow of the IEEE, a Fellow of the AAIA, and an ACM Distinguished Engineer.
Books / Articles
API Design Book
API Design Book
I have written 2 computer science textbooks, published over 40 peer-reviewed articles, and I hold 10 granted patents. My most recent book focuses on how to design clean and robust software interfaces in C++.
Movies
Finding Nemo
Cars
The Incredibles
Martin's Head
Ratatouille
WALL-E
Presto Animation System
Martin's Head
I led software engineering teams at Pixar where I helped develop technology for many of Pixar's early movies and short films. My feature film credits include the Academy Award Winning movies Finding Nemo, The Incredibles, Ratatouille, and WALL-E, and the Academy Award Nominated movie Cars.
I was also part of the original software engineering team that developed Pixar's Presto Animation System, which won an Academy Scientific and Engineering Award. And I was the hair model for Mr. Incredible.
Career
Apple
Software Architect (5 years)
As a senior engineering leader within the AI/ML division, I was responsible for the architecture and design of major components of the Siri virtual assistant. I worked on software improvements to Siri that have been deployed to over a billion devices across 40 locales. This includes features that run on the entire range of Apple devices from iPhones and Macs through HomePods, Apple Watches, and CarPlay units.
Apple
PullString
Co-Founder / CTO (8 years)
I co-founded the AI technology company PullString (originally called ToyTalk). Our vision was to use AI to make it effortless to talk with the voice-enabled technology that surrounds us. As CTO, I was responsible for developing the PullString SaaS Platform, which included the powerful PullString Converse web app. This let non-technical users create voice applications for popular devices like Amazon Echo and Google Home. PullString was acquired by Apple in 2019.
PullString
Pixar
Lead Software Engineer (5 years)
I was a lead engineer in Pixar's Studio Tools R&D department, where I managed a team of engineers building next-generation animation tools for our artists. This involved building and maintaining a large C++ desktop application with extensive scripting APIs accessible via C++ and Python. I also worked directly as a C/C++ engineer on Pixar's in-house filmmaking software, adding new features from deep core changes all the way up to new GUI workflows.
Pixar
SRI International
Research Engineer (5 years)
At SRI, I worked in the Perception program of the Artificial Intelligence Center, working on the network-based 3-D terrain visualization system called TerraVision. This effort also involved international standards-based work as chair of the GeoVRML working group, and work on a scheme to index all geospatial information on the Internet, referred to as the GeoWeb. I was also elected as a Director of the Web3D Consortium 2 years running.
SRI International
University of Edinburgh
Ph.D. in Computer Science (4 years)
My doctoral research involved applying models of human visual perception to level of detail (LOD) systems so that we can remove imperceptible detail from a 3D scene and hence optimize the frame rate. This translated into various SIGGRAPH courses and a book published by Morgan Kaufmann. During this time, I also developed the 3D Mines game for the SGI range of computers.
University of Edinburgh
University of Strathclyde
B.Sc. in Computer Science (4 years)
I graduated with a 1st class honors in Computer Science (summa cum laude). My undergraduate projects included writing generators for Mandelbrot and Julia sets, Koch curves, and Hilbert space-preserving curves, where I developed a novel adaptive-recursion optimization for the Mandelbrot set calculation. I also developed a fully functional 3-D spreadsheet, called Cerberus.
University of Strathclyde
Apple
PullString
Pixar
SRI International
University of Edinburgh
University of Strathclyde
Awards / Honors
Get The Point
  • Fellow of the IEEE
    (Institute of Electrical and Electronics Engineers)
  • Fellow of the AAIA
    (Asia-Pacific Artificial Intelligence Association)
  • Distinguished Engineer of the ACM
    (Association for Computing Machinery)
  • Alumnus of the Year
    (University of Strathclyde)
History
60 CLR: FOR Y=0 TO 34: FOR X=0 TO 15: READA 70 C=C+A: POKE 39984+Y*16+X,A: NEXTX 80 READA: IF A<>C THEN PRINT "?ERROR IN LINE" 100+Y*10: END 90 C=0: NEXTY: PRINT "O.K." 100 DATA 128, 192, 192, 224, 240, 240, 248, 252, 252, 254, 248, 216, 28, 12, 14, 4, 2744 110 DATA 76, 92, 157, 169, 45, 133, 51, 133, 55, 169, 156, 133, 52, 133, 52, 162, 1768 120 DATA 62, 169, 0, 157, 191, 2, 202, 208, 250, 162, 0, 168, 189, 48, 156, 153, 2117 130 DATA 192, 2, 232, 200, 200, 200, 224, 16, 208, 242, 173, 53, 3, 141, 46, 208, 2340 140 DATA 169, 11, 141, 255, 7, 173, 14, 208, 208, 5, 169, 24, 141, 14, 208, 173, 1920 150 DATA 15, 208, 208, 17, 169, 50, 141, 15, 208, 173, 16, 208, 41, 127, 141, 16, 1753 160 DATA 208, 169, 0, 133, 2, 173, 21, 208, 9, 128, 141, 21, 208, 96, 173, 15, 1705 170 DATA 208, 201, 246, 208, 1, 96, 238, 15, 208, 96, 173, 15, 208, 201, 50, 208, 2372 180 DATA 1, 96, 206, 15, 208, 96, 165, 2, 201, 116, 48, 17, 173, 16, 208, 9, 1577 190 DATA 128, 141, 16, 208, 165, 2, 233, 116, 10, 141, 14, 208, 96, 173, 16, 208, 1875 200 DATA 41, 127, 141, 16, 208, 165, 2, 10, 105, 24, 141, 14, 208, 96, 165, 2, 1465 210 DATA 208, 1, 96, 198, 2, 76, 182, 156, 165, 2, 201, 158, 208, 1, 96, 230, 1980 220 DATA 2, 76, 182, 156, 173, 0, 220, 201, 126, 208, 3, 76, 170, 156, 201, 125, 2075 230 DATA 208, 3, 76, 158, 156, 201, 123, 208, 3, 76, 222, 156, 201, 119, 208, 3, 2121 240 DATA 76, 232, 156, 201, 122, 208, 6, 32, 170, 156, 76, 222, 156, 201, 121, 208, 2343 250 DATA 6, 32, 158, 156, 76, 222, 156, 201, 118, 208, 6, 32, 170, 156, 76, 232, 2005 260 DATA 156, 201, 117, 208, 6, 32, 158, 156, 76, 232, 156, 96, 32, 228, 255, 201, 2310 270 DATA 17, 208, 3, 76, 158, 156, 201, 29, 208, 3, 76, 232, 156, 201, 145, 208, 2077 280 DATA 3, 76, 170, 156, 201, 157, 208, 3, 76, 222, 156, 96, 32, 67, 156, 32, 1811 290 DATA 244, 156, 32, 60, 157, 165, 197, 201, 60, 240, 22, 173, 0, 220, 201, 112, 2240 300 DATA 48, 15, 160, 8, 162, 100, 234, 234, 202, 208, 251, 136, 208, 246, 76, 95, 2383 310 DATA 157, 165, 2, 74, 74, 141, 54, 3, 173, 15, 208, 233, 50, 74, 74, 74, 1571 320 DATA 141, 55, 3, 173, 15, 208, 201, 50, 208, 5, 169, 0, 141, 55, 3, 160, 1587 330 DATA 4, 173, 55, 3, 208, 5, 173, 54, 3, 144, 33, 173, 55, 3, 141, 167, 1394 340 DATA 2, 10, 10, 10, 141, 56, 3, 162, 5, 173, 167, 2, 10, 144, 1, 200, 1096 350 DATA 141, 167, 2, 202, 208, 243, 109, 56, 3, 144, 1, 200, 109, 54, 3, 144, 1786 360 DATA 1, 200, 141, 168, 2, 140, 169, 2, 173, 168, 2, 237, 169, 2, 105, 4, 1683 370 DATA 141, 168, 2, 173, 55, 3, 201, 16, 48, 6, 238, 169, 2, 238, 168, 2, 1630 380 DATA 173, 168, 2, 208, 3, 238, 168, 2, 201, 1, 208, 3, 238, 168, 2, 201, 1984 390 DATA 2, 208, 3, 238, 168, 2, 201, 3, 208, 3, 238, 168, 2, 201, 255, 208, 2108 400 DATA 24, 173, 55, 3, 240, 16, 201, 16, 240, 12, 201, 8, 240, 8, 201, 32, 1670 410 DATA 240, 4, 169, 0, 240, 3, 238, 168, 2, 173, 168, 2, 201, 254, 208, 13, 2083 420 DATA 173, 54, 3, 201, 31, 208, 6, 206, 169, 2, 238, 168, 2, 173, 168, 2, 1804 430 DATA 141, 74, 158, 173, 169, 2, 141, 75, 158, 173, 0, 0, 141, 52, 3, 173, 1633 440 DATA 21, 208, 41, 127, 141, 21, 208, 96, 0, 0, 0, 0, 0, 0, 0, 0, 863 60 CLR: FOR Y=0 TO 34: FOR X=0 TO 15: READA 70 C=C+A: POKE 39984+Y*16+X,A: NEXTX 80 READA: IF A<>C THEN PRINT "?ERROR IN LINE" 100+Y*10: END 90 C=0: NEXTY: PRINT "O.K." 100 DATA 128, 192, 192, 224, 240, 240, 248, 252, 252, 254, 248, 216, 28, 12, 14, 4, 2744 110 DATA 76, 92, 157, 169, 45, 133, 51, 133, 55, 169, 156, 133, 52, 133, 52, 162, 1768 120 DATA 62, 169, 0, 157, 191, 2, 202, 208, 250, 162, 0, 168, 189, 48, 156, 153, 2117 130 DATA 192, 2, 232, 200, 200, 200, 224, 16, 208, 242, 173, 53, 3, 141, 46, 208, 2340 140 DATA 169, 11, 141, 255, 7, 173, 14, 208, 208, 5, 169, 24, 141, 14, 208, 173, 1920 150 DATA 15, 208, 208, 17, 169, 50, 141, 15, 208, 173, 16, 208, 41, 127, 141, 16, 1753 160 DATA 208, 169, 0, 133, 2, 173, 21, 208, 9, 128, 141, 21, 208, 96, 173, 15, 1705 170 DATA 208, 201, 246, 208, 1, 96, 238, 15, 208, 96, 173, 15, 208, 201, 50, 208, 2372 180 DATA 1, 96, 206, 15, 208, 96, 165, 2, 201, 116, 48, 17, 173, 16, 208, 9, 1577 190 DATA 128, 141, 16, 208, 165, 2, 233, 116, 10, 141, 14, 208, 96, 173, 16, 208, 1875 200 DATA 41, 127, 141, 16, 208, 165, 2, 10, 105, 24, 141, 14, 208, 96, 165, 2, 1465 210 DATA 208, 1, 96, 198, 2, 76, 182, 156, 165, 2, 201, 158, 208, 1, 96, 230, 1980 220 DATA 2, 76, 182, 156, 173, 0, 220, 201, 126, 208, 3, 76, 170, 156, 201, 125, 2075 230 DATA 208, 3, 76, 158, 156, 201, 123, 208, 3, 76, 222, 156, 201, 119, 208, 3, 2121 240 DATA 76, 232, 156, 201, 122, 208, 6, 32, 170, 156, 76, 222, 156, 201, 121, 208, 2343 250 DATA 6, 32, 158, 156, 76, 222, 156, 201, 118, 208, 6, 32, 170, 156, 76, 232, 2005 260 DATA 156, 201, 117, 208, 6, 32, 158, 156, 76, 232, 156, 96, 32, 228, 255, 201, 2310 270 DATA 17, 208, 3, 76, 158, 156, 201, 29, 208, 3, 76, 232, 156, 201, 145, 208, 2077 280 DATA 3, 76, 170, 156, 201, 157, 208, 3, 76, 222, 156, 96, 32, 67, 156, 32, 1811 290 DATA 244, 156, 32, 60, 157, 165, 197, 201, 60, 240, 22, 173, 0, 220, 201, 112, 2240 300 DATA 48, 15, 160, 8, 162, 100, 234, 234, 202, 208, 251, 136, 208, 246, 76, 95, 2383 310 DATA 157, 165, 2, 74, 74, 141, 54, 3, 173, 15, 208, 233, 50, 74, 74, 74, 1571 320 DATA 141, 55, 3, 173, 15, 208, 201, 50, 208, 5, 169, 0, 141, 55, 3, 160, 1587 330 DATA 4, 173, 55, 3, 208, 5, 173, 54, 3, 144, 33, 173, 55, 3, 141, 167, 1394 340 DATA 2, 10, 10, 10, 141, 56, 3, 162, 5, 173, 167, 2, 10, 144, 1, 200, 1096 350 DATA 141, 167, 2, 202, 208, 243, 109, 56, 3, 144, 1, 200, 109, 54, 3, 144, 1786 360 DATA 1, 200, 141, 168, 2, 140, 169, 2, 173, 168, 2, 237, 169, 2, 105, 4, 1683 370 DATA 141, 168, 2, 173, 55, 3, 201, 16, 48, 6, 238, 169, 2, 238, 168, 2, 1630 380 DATA 173, 168, 2, 208, 3, 238, 168, 2, 201, 1, 208, 3, 238, 168, 2, 201, 1984 390 DATA 2, 208, 3, 238, 168, 2, 201, 3, 208, 3, 238, 168, 2, 201, 255, 208, 2108 400 DATA 24, 173, 55, 3, 240, 16, 201, 16, 240, 12, 201, 8, 240, 8, 201, 32, 1670 410 DATA 240, 4, 169, 0, 240, 3, 238, 168, 2, 173, 168, 2, 201, 254, 208, 13, 2083 420 DATA 173, 54, 3, 201, 31, 208, 6, 206, 169, 2, 238, 168, 2, 173, 168, 2, 1804 430 DATA 141, 74, 158, 173, 169, 2, 141, 75, 158, 173, 0, 0, 141, 52, 3, 173, 1633 440 DATA 21, 208, 41, 127, 141, 21, 208, 96, 0, 0, 0, 0, 0, 0, 0, 0, 863
Your CommodoreGet The Point
Back in the 80s, you would buy computer magazines with source code listings and carefully type these programs into your computer to run them. My first piece of paid software was a program that was published in Your Commodore magazine when I was 16 years old.
This Commodore 64 BASIC program loaded a series of 6502 machine code instructions into memory and ran them. It produced a pointer that could be moved on-screen with a joystick to select characters. While unremarkable today, this was novel for a computer that had no built-in notion of a mouse, cursor, or windows.
Another way you could publish software in the 80s was through Shareware. This is where people sent you a check in the mail and you sent them back a floppy disk. I sold a popular shareware text editor for the Amiga 500 called EdWord.
EdWord had advanced features like multiple documents, split screen, macros, symbolic indenting, source code highlighting, and command automation, all the way back in the 80s.
Get The Point
Personal Stuff
I gained my 2nd Degree Black Belt in WTF Taekwondo training under Master Steve Rapport. At University, I practiced Tukido under Grand Master Hock Aun Teh and was four-time British sparring champion. I was awarded my "Full Blue" for national-level martial arts achievement from Strathclyde University. The above video is my jumping spinning hook kick break from my 2nd Dan Black Belt test.
© 2025 Martin Reddy. All rights reserved.