Showing posts with label code. Show all posts
Showing posts with label code. Show all posts

No posts for a wee while

Mike's Notes

I was on holiday for the last few weeks and am back now. There will be no blog posts, newsletters or meetings until Pipi Core is back up and running.

Update 27/05/2026

Lots of surprises. Making rapid progress. The peace and quiet are bliss.

Update 31/05/2026

The problem and solution are how things are named. Pipi auto-generates thousands of code names using multiple pattern languages, and all the naming conventions require many minor fixes for several unexpected reasons after migrating from a developer laptop to a production server environment. Everything else is absolutely fine.

Other naming problems are also being solved now, including:

  • The rapid development of Boxlang by Ortus has brought forward another challenge. Pipi 10 will be migrated to run on top of Boxlang in 2027 to support multiple languages, including C++, CFML, COBOL, Go, Java, JavaScript, PHP, Python, Rust, etc.
  • Future integration with cloud-based LLMs.
  • Future integrations with Office365, Google Workspace, Zoho, LibreOffice, etc.

The common solution is to create standardised naming systems that are simple, stable, robust, schema-based, versioned, self-documenting, and extensible to meet unanticipated future needs.

This is done by replacing code-based naming rules with database-driven ones that can be easily edited in the future via an admin UI.

90% of these names are internal, hidden in the closed core, and how they work and what they are will not be discussed here. The rest will be publicly and fully documented as part of the open-source workspaces for developers to work with.

Update 02/06/2026

I'm changing the disclosure boundary between the Pipi closed-core and open-source workspaces. Previously, "disclose everything unless there is a security reason not to". This is now changed to "disclose on the basis of need to know".

Closed-core accounts for 90% and open-source workspaces for 10% of lines of code, databases, etc.

This will reduce the documentation burden, given Pipi's vast scale. So, the open-source workspaces will be fully shared and documented on GitHub, etc, without restriction. This includes;

  • Standards schema
  • Ontologies
  • Parameters
  • Laws of physics
  • HTML + CSS
  • Algorithms
  • Module DDD models
  • Workflow diagrams
  • Documentation
  • API schema
  • UI code
  • etc

This also means some existing technical documentation about the closed-core will become hidden and only available internally.

Update 07/06/2026

Pipi Core is the IDE used to edit Pipi Core (AKA: which came first, the chicken or the egg?). Temporary UIs have been created and are being used across multiple engines to edit the names in use. This is much faster than directly editing data, which had to be done initially. The next step will be turning auto-generation back on. Once that's done, temporary UIs will be used to build permanent UIs. More automation will then be enabled via the UIs, and so on, as Pipi Core builds itself with a human in the loop.

Update 08/06/2026

The list of code cases available to use now for auto-generated naming, I/O translation, etc with examples, includes;

  • camelCase: userProfilePicture
  • kebab-case: user-profile-picture
  • PascalCase: UserProfilePicture
  • snake_case: user_profile_picture
  • SCREAMING_SNAKE_CASE: USER_PROFILE_PICTURE
  • Train-Case: User-Profile-Picture
  • flatcase: userprofilepicture
  • UPPER-CASE-KEBAB-CASE: USER-PROFILE-PICTURE
  • Sentence case: User profile picture
  • Title Case: User Profile Picture
  • middot·case: user·profile·picture
  • dot.case: user.profile.picture
  • UPPER CASE: USER PROFILE PICTURE
  • lowercase: user profile picture

Update 12/06/20026

Checking that these changes to variable names and internal messaging do not clash with the GΓΆdel Machine.

Update 17/06/2026

The DevOps Engine (dvp) has unexpectedly proven to be critical to solving this puzzle. Mostly fixed last night. Watching the rather excellent live Google talk, Beyond the GPU: Maximising goodput with self-healing AI infrastructure, this morning has given me valuable insights into how to fix the remaining issues by reviewing Google HPC YAML files. 😎😎 Sometimes insights come from the strangest places.

Update 01/07/2026

The main work now is rapidly configuring Pipi for production and full autonomous automation. Using Google Search AI Mode (Gemini) and then Grammarly Pro makes the work easier and 100x faster.

  • I have decided to have Pipi re-render the many Ajabbi draft public websites with the new and missing developer information. (20K pages)
  • The website's .robot.txt file will then be unlocked to enable search engines.
  • The HTML will be updated to make it easier for AI to read.
  • This blog will be imported into Pipi, cleaned up, re-exported from Pipi, and published to Blogger via the API.
  • The new posts created in Pipi will return to A Sandy Beach to discuss something already built rather than being built.

Update 02/07/2026

The DevOps and IaC engines are getting rapid data model overhauls. The IaC engine is a great test for the variable names. I'm building a capability into Pipi to autonomously and automatically run OpenTofu and Ansible, initially targeting the Pipi Data Centre, then GCP and AWS for deployments. It's going very well and making rapid progress.

Update 05/07/2026

Pipi will initially run the open-source enterprise applications on Google Cloud Run and Google Cloud Storage (GCS). The code is complete and will be very low-cost to run, giving Ajabbi, a bootstrapping-purpose startup, a very long runway.

Update 18/07/2026

The job has now shifted to configuring, networking and deploying many physical servers. Installing software, including Pipi, labelling cables and rack gear, throwing out junk, tidying, etc., leaving nothing to chance. Shipping delays are holding up part deliveries.

Update 23/07/2026

On the basis of open collaboration and credits for experimentation, I was going to offer Google exclusive use of Pipi for a period (as a thank you) before Pipi open-source is donated to the Cloud Native Computing Foundation for all to use.

Make money to provide a service.

I'm getting exasperated with XWF. They are the external sales contractors to Google, and since 2021, they regularly contact me.

  • Selling GCP products (No need; I'm already convinced).
  • Acting as gatekeepers to any contact with Google Engineers to discuss novel integration options, which is the actual issue. How to combine Gemini (an LLM) and Pipi (non-LLM) to make something much better.
  • They are all very nice, but a complete waste of my time. No more XWF meetings, folks.

So, I have decided to target integration with OpenRouter (and its alternatives) instead of Gemini and open up the Pipi developer platform (it is big and coming 😎) to enable developers from Alibaba, Alice AI, Anthropic, AWS, Azure, ByteDance, DeepSeek, Google, IBM, Meta, Mistral, Moonshot AI, Naver, OpenAI, Oracle, Palantir, Sarvam AI, xAI, etc, and anyone else, to enable integrations that are optimal, 100% secure and vetted, with everything publicly verifiable.

Pipi closed-core will never be for sale; this year it's getting a non-profit foundation behind it, a bit like Patagonia. I'm open to all genuine offers of assistance, collaboration and experimentation with no strings attached. Contact me.

Don't send sales engineers

Send a senior, highly experienced engineer/architect/chief scientist who loves a big fat problem and has time for an open chat without a pitch or an agenda, and just see where it goes.

If you want to meet in person, expect to work collaboratively at a whiteboard or blackboard like a real mathematician. Plus coffee, of course. 😎 To see how this works, watch the seminars at the London Institute of Mathematical Sciences, or the recorded physics seminars at Perimeter.

Pipi is rooted in biology and the laws of physics, so you need a very solid background in advanced sciences (microbiology, biochemistry, mathematics, philosophy, particle physics, thermodynamics, complex adaptive systems, etc).

Please, no venture capitalists or private equity. You're wasting your time. Go find something else to plunder. Pipi is a gift to humanity.


Being very high-functioning Asperger's (autism) with hyperphantasia, plus multiple synesthesias, I think visually at lightning speed and output solutions as fast as I can draw. I love solving very hard problems that matter. I can only write very slowly with the help of assistive technology, so I prefer video meetings with good spoken English, slides and time for trading quick engineering drawings.

Pipi is designed to run massive enterprise systems for socially useful critical infrastructure on every platform in many languages and writing systems.

The intention is to make life better for all of humanity by destroying waste, failure and crippling bureaucracy in;

  • Health systems (hospitals)
  • Transport systems (rail, road, air, shipping)
  • Sewerage
  • Drinking water
  • Land drainage
  • Nature conservation
  • Built infrastructure
  • Electricity networks
  • GLAM (galleries, libraries, archives, museums)
  • Farming (agriculture, forestry, aquaculture, horticulture
  • etc
Infant mortality rates will be the KPI

Pipi makes these systems self-assembling, self-managing, resilient and adaptive. I had to solve hundreds of very big, hard, complex problems in parallel to make this work. Some of them were abandoned research by others, who couldn't make them work, so I solved them. The answers were there, hidden in plain sight. Invisible due to a lack of imagination or courage.

Easy for me, because I can do it visually in my mind, run simulations of thousands of components while sleeping, including the testing, then wake up and just build; it always works 100% (been doing it for decades). That's why no one else has cracked this problem. I can remember everything I have designed this way since age 4 in great detail. Curiosity-driven learning turns everything I read that's interesting into a moving 4d model in my mind; there are tens of thousands of these shimmering mental models, and they self-assemble when I shut my eyes to solve a problem. Each model grows in detail and size as I learn more. I can fly through the models, exploring and touching them. Really cool.

Ahaa moments most days

Some days, I wake up, and the insights and designs pour out of my head like a firehose, and I can barely keep up even after outputting 20+ drawings on A4 paper in a day. Now, there are many thousands of colour-coded drawings in ring binders.

I turn the growing backlog of these designs into data models, code, and documentation with references by giving simple, direct instructions to Google Search AI Mode (Gemini), which teaches me new skills and gives me a response to edit, test, correct, and use. I'm going 100x faster, like a bat out of hell, the equivalent of a crack team of pre-AI developers. 😎 And I'm getting a lot faster.

I rely 100% on intuition when surfing a sea of 4D visual mental models. I really don't understand how the rest of you can only think in words, because I can't.

I have been very lucky

My grandmother Bessie showered me with attention and love, gave me endless things to pull apart to see how they worked, and took me to meet very clever people in a small-minded backwater town.

Family holidays in wild New Zealand, next to rivers, beaches, forests and mountains, which ignited a lifelong obsession with the patterns of nature, the why.

My best friend right through school; he was the brightest kid in NZ.

My high school science teacher, Alan Morgan, let me play in the chemistry lab, doing experiments after school unsupervised for several years, and taught me the scientific method on my very last day at school, the most important thing I learned in 12 wasted years.

The wise old tradesmen, who took a skinny kid from sweeping the floor to being able to make anything, by learning on the job, trying hard, and having my butt kicked.

Nelson Mandela taught me to have the courage of my convictions and never give up.

The sculptor Neil Dawson and the set designer Tony Geddes taught me how to work authentically.

My blind friend Grant, who cut down bushes with a chainsaw and made and gave away $60 M, teaching me quiet courage and human decency.

The magnificent 50,000 working people of South Christchurch, who trusted me to lead a volunteer residents army doing recovery for 3 years, after the Christchurch Earthquake, teaching me humility and valuable leadership skills gained by trial and error in the moment.

My beloved Tracy, the bravest woman I have ever met, the only paraplegic to do the Coast-to-Coast Iron Man, who married a lost autistic male and made me a much better man. Her unwavering devotion, encouragement and loyalty made all this possible.

They all shaped me; I can't thank them enough. May their memories be a blessing.

The future is open, at the edge of chaos

Update 28/07/2026

Most of the equipment has arrived, and the small data centre setup is coming together. More deliveries later this week. It's already running a lot better and is much more productive.

Update 30/07/2026

My creative problem-solving and build process is evolving, and the loop is getting faster. Works every time.

  • Understanding the problem starts with reading or talking with someone, watching a YouTube talk, or listening to the radio.
  • Do lots of research, mostly reading books (days to months).
  • Drink plunger coffee.
  • Print off a paper(s) or article(s) and file it in an A4 3-hole ring-binder.
  • Drink Chamomile tea.
  • Daydream (solutions come within hours or months later).
  • Drink plunger coffee.
  • Draw the solution as many colour-coded A4 architecture drawing(s).
  • Drink more coffee (Cappuccino).
  • File the drawing(s) with the printed paper.
  • Use the drawings to prompt Google Search AI Mode (free) with detailed instructions on what to build.
  • Output teaches me, describes data model, code, documentation.
  • Print off and file with the rest.
  • Walk a dog. Plant a tree. Watch the sun rise.
  • Read the printed AI output, colour-code, add doodles, correct, test, edit names, build, use in Pipi, while listening to music. (I don't copy-paste. I manually type to copy, because it helps me learn and understand.)
  • Throw away all the paper except for the original research, which is moved from DevOps to the research library.
  • Pipi then generates self-documentation, including mermaid drawings.
  • Repeat.

Each loop cycle takes weeks to years. There are hundreds running in parallel at any one time. It's a pull system. I work on Pipi when something needs to be solved, and look up my library of solutions. Totally intuitive, just like an artist, not an engineer, and always fun like a kid playing.

These changes are made possible because of the detailed work done over the last few months removing barriers, including modifications to Pipi, reorganising space, equipment, and routines.

I think I have now solved all major problems to get Pipi 9 Core (Loki) running 24x7x52. Anything else that pops up can be solved along the way as part of maintenance.

Now to execute very fast.

Resources

References

  • Reference

Repository

  • Home > Ajabbi Research > Library >
  • Home > Handbook > 

Last Updated

30/07/2026

No posts for a wee while

By: Mike Peters
On a Sandy Beach: 15/05/2026

Mike is the inventor and architect of Pipi and the founder of Ajabbi.

I was on a no-coding holiday for the last few weeks to clear my mind, and it has been great. I am back on the job today.

Suspended

Until the closed-source Pipi Core is back up and running 100% on autopilot, 10x faster, the following are suspended.

  • New posts "On a Sandy Beach
  • All newsletters, including the weekly Friday Report and the monthly Ajabbi Research Newsletter.
  • The fortnightly online Open R&D meeting.

Rapid refocus

  • A new developer area with five coding screens, designed to be more productive for hypervisual learners.
  • A better library has been set up for my A4 drawings in ring binders, the many reference books I use, and more bookshelves are on the way.
  • The server rack has been moved to a better location.
  • The light levels have been adjusted.
  • A big office tidy is almost done. An office-work-only desk has yet to be set up with a cat bed included.
  • A separate area with no screens for the happy cat, coffee, music, reading and drawing.

Less is more

Minimise screen time to be more productive at work. The new setup is also much less tiring.

Get the job done

The good thing is that, with a holiday and lots of drawing, I now have mental clarity about what needs fixing and how to fix it. Mainly, quite delicate changes here and there, organised into a list of steps. Now, I need to concentrate on one thing only: go as fast as possible, without meetings, post-deadlines, phone calls, or other distractions.

How

1. Use an AI workforce

Be the architect, and AI fills in the dots to make it happen.

Use Google Search AI mode (Gemini) to generate 99% of the code in one-page chunks (including references) to copy and paste, then manually change the variable names and SQL. Careful, test everything, resulting in 100x faster progress. Know how everything works and rapidly raise personal skill level.

2. Then build a cathedral

Make a wooden scale model of a cathedral for the builders. Google Search AI mode (Gemini) makes each brick, and Pipi Core assembles the bricks into floors, arches, walls, and vaults...

Speed is king

With the 100x coding productivity gains from Google Search AI mode (Gemini), plus the 10x10x10x speedup of Pipi Core currently underway over the next few months, what previously took a year will be done in hours and better.

Phase transitions

Once these initial migration issues from laptop to server are resolved, further transitions can be anticipated as the number of engines rapidly increases beyond 20. Increasing the number of engines slowly changes the whole system's behaviour from deterministic to probabilistic and adaptive.

Here is a partial list of transitions expected as the number of engines increases from 0 to 200. The actual numbers are a bit of a guess.

  • 20 engines enable Pipi 9 Core in a simple, deterministic structure.
  • 40 engines enable a workspace with a UI for administering Pipi Core.
  • 60 engines enable self-generation of user documentation.
  • 80 engines enable REPL and IAC (infrastructure-as-code).
  • 100 engines enable Workspaces for different user accounts.
  • Different Pipi 9 editions are made with the same engines, which recombine differently in response to the external environment.
  • And so on until...
  • 200 engines self-organise into a multi-layered complex fluid structure with probabilistic behaviour and emergent properties, as engines also act as agents.
  • 200+ engines enable Pipi 10 to interact with externally cloud-hosted LLMs, combining the very different strengths of both.

Vibing, Harness and OODA loop

Mike's Notes

Wise words from Oskar Dudycz. Subscribe to Architecture Weekly, it's awesome. 😎

Resources

References

  • Reference

Repository

  • Home > Ajabbi Research > Library > Subscriptions > Architecture Weekly
  • Home > Handbook > 

Last Updated

30/04/2026

Vibing, Harness and OODA loop

By: Oskar Dudycz
Architecture Weekly: 27/04/2026

Software Architect & Consultant / Helping fellow humans build Event-Driven systems. /Blogger at https://event-driven.io/ . OSS contributor https://github.com/oskardudycz /Proud owner of Amiga 500.

On why Vibing and Harness are not new and why feedback loops are important.

Hey, have a look at what I made during the weekend. I had some time, grabbed a beer, turned on the computer and tried to code this feature. If I could do so much during the weekend, how much could you and your team do with it in 2 weeks?

It’s almost a 1:1 quote of what I heard from the startup founder I worked with over 10 years ago. I’m sure that you’ve heard similar phrases from people you worked with. We all know the annoying type of person who doesn’t code anymore but thinks, “I still got it!”. Then they threw a piece of stuff at you to “just fine-tune it a bit and do final touches”. Then they’re the first ones to ask “Why so long?“.

Nowadays, the Internet is full of such people. They shout about what they did with Claude or how much progress LLM tools have made. Some even predict the end of coding. I already wrote that this is wrong perspective. I won’t repeat that, but I want to say that…

Vibing isn’t new and isn’t always an issue.

I’m saying that LLM tools are an appraisal for ignorance. The more ignorant we are of the topic we’re working with, the better we see the outcomes. And that, by itself, is not always bad, as there’s power in ignorance if we focus on getting it done with the simplest tools we have.

Still, this can be terrible if we fall in love too much with what we’ve vibed.

To understand why that “weekend beer” energy is both a superpower and a liability, we need to look at the OODA Loop.


Disclaimer, it’s not a competition for Ralph Wiggum Loop. It’s much older and generic.

Military strategist John Boyd developed the OODA loop (Observe, Orient, Decide, Act) for fighter pilots. In a dogfight, the pilot who cycles through these four stages the fastest and most accurately survives.

In software, the “dogfight” is the gap between your intent and the production-ready feature.

OODA loop is built from four steps:

  1. Observe - This is the intake of raw, unfiltered information. In our world, this means looking at the state of the system.
  2. Orient - This is the most critical and difficult stage. It’s where you filter your observations through your experience, culture, and technical knowledge.
  3. Decide - Based on your orientation, you formulate a hypothesis.
  4. Act - You execute.

Getting back to my favourite founder and LLM-based tools.

The reason founder could build a PoC in a weekend while the team needed more than two weeks is that he bypassed the Observe and Orient phases. He went straight from a vague idea to Act.

If we skip or brush past the observation step, it feels like lightning speed. If the fancy UI grid is there and it does something we wanted, we move on. We’ve outsourced Orientation to our own ego. It’s too easy to assume that because we wrote it, it works.

Observation is the intake of raw data. In a professional environment, our eyes aren’t enough. We need a Harness. If we don’t have automations, tests, integration tests, and pristine traces, we aren’t observing the system; we’re just looking at it. If the inputs are messy, our observation is clouded.

But real engineering, the kind that takes those “two weeks”, is about closing the loop properly. That’s also where we need different perspectives and knowledge sharing.

Orientation is where you process those observations. This is the part where LLMs make us feel smarter than we are. If we don’t understand how a database handles concurrent connections, our “orientation” of a generated script will be shallow. We’ll see code that “looks” right, decide it’s fine, and act by deploying it.

The “I still got it” crowd loves the Decide and Act phases because that’s where the visible progress happens. LLM tools have made these phases nearly instantaneous. We can decide to build a feature and have the code for it in ten seconds.

The problem is that the faster we Act, the faster we need to Observe. If our “Act” phase takes seconds but our “Observe” phase requires a manual weekend of clicking around and drinking beer, our OODA loop is broken. We’re just generating a pile of stuff that we haven’t actually verified.

That’s why the team usually needs more than an imaginary “two weeks”. They are not “fine-tuning” the single-brilliant-dude masterpiece. They are building the infrastructure required to make the OODA loop sustainable.

And to make that possible, they need to run the full loop: Observe, Orient, Decide, Act. And do it multiple times. That takes time, but it’s required to assess the direction, automate what needs to be automated, and ensure they can iterate further and run this loop sustainably. That’s critical for delivering the outcome at the expected pace.

Of course, there’s a danger here, overfocusing on the Orient and Decide can lead to overengineering, building stuff we don’t need. That’s where ignorance can be blissful, especially when we connect it with humility. Being humble about what we don’t know and trying things the easiest way, then learning and making enhancements. Still, humility fails under deadline pressure. The harness doesn’t.

Let me give you…

The example

I’m adding proper Observability and Open Telemetry to Emmett right now. I spent some time working on it and instrumented the first component: Command Handling.

Of course, I had tests to prove it works, but I don’t trust them enough, and I wanted to try it on a real sample, since you never know until you run it. Even the best test suite won’t tell you all.

So I decided to plug it into the sample. See if it works, how ergonomic the API is and how it fits conventions in this area.

To do it, I decided to use Grafana stack and set it up with Docker Compose. So, stable, boring stack. Not going to lie, I vibed the config. Not that there are no docs, but I intentionally wanted to see the typical config people use.

If someone says LLM-based tools are great at proof of concepts, they don’t run the stuff they vibed. If I made the observation based on the initial config, then an oriented decision would be that it won’t work. Of course, then I did the typical back-and-forth, with the LLM tool doing some Linux command Voodoo to make it work. Once. Then, if you try to repeat it, you won’t know how to do it without doing Voodoo again.

Again, that’s not much different from the other stuff we do. I’m sure that you had multiple cases, when someone didn’t use Continuous Deployment tools, but clicked through Azure, AWS, GCP portal, deployed the stack, and then there was no trace on how to set it up again (e.g. to have a different environment for testing or demos for customers).

So, we need a harness, we need a leash to keep our process on track.

How to do the harness? My advice is to start simple. We may ask LLMs to give us shell scripts, and we may ask them to run them multiple times. We also need experience and knowledge of what we want to achieve and the tools we use. It’s fine not to remember all the YAML config to set up the Grafana stack, but it’s not fine not to understand why you even use it, how it relates, and how to set it up.

Still, our first loop can close on the first working solution, even a manually vibed one. But that’s not even a PoC. We need to automate them.

I asked LLM to take notes on what issues it had, and it solved them. Then, based on that, I asked to research how to code it in TypeScript. And to use tools I know, used in past, validating if there are no new more modern ones. For instance, I was a big fan of Gulp.js and Bullseye in the past, but they’re mostly dead. I wanted to have something in the same spirit, using native, maintained tooling.

I ended up with the following tools:

  • execa for running shell scripts,
  • native fetch for calling http endpoints,
  • native Node.js test tools for checking if the stack works as expected.

Then I asked it to create the script to automate the shell Voodoo they did to make Grafana stack and Docker Compose work.

Essentially, it should:

  1. Run Docker Compose script starting up services (Grafana, Prometheus, Loki, Tempo, PostgreSQL, etc.).
  2. Wait for them to check when they’re ready (it usually takes some time).
  3. Start the application and make a request.
  4. Check if the predefined dashboard with Emmett metrics appears, and shows expected traces and metrics.

Initial diagnostic tools looked like that

async function fetchWithDiag(label: string, url: string, init?: RequestInit) {
  const res = await fetch(url, init);
  if (!res.ok) {
    const body = await res.text().catch(() => '(could not read body)');
    console.error(`\n  ✗ ${label} → HTTP ${res.status}\n  body: ${body}\n`);
  }
  return res;
}
async function diagnoseCollector() {
  const text = await fetch(URLS.otelCollectorMetrics)
    .then((r) => r.text())
    .catch(() => 'unreachable');
  const emmett = text
    .split('\n')
    .filter((l) => l.startsWith('emmett_') && !l.startsWith('#'))
    .slice(0, 5);
  console.log(
    emmett.length
      ? `\n  collector /metrics (emmett lines):\n  ${emmett.join('\n  ')}`
      : '\n  collector /metrics: no emmett_* lines found',
  );
}
async function diagnosePrometheus() {
  const json = await fetch(
    `${URLS.prometheus}/api/v1/label/__name__/values`,
  )
    .then((r) => r.json() as Promise<{ data: string[] }>)
    .catch(() => ({ data: [] as string[] }));
  const emmett = json.data.filter((n) => n.startsWith('emmett_'));
  console.log(
    emmett.length
      ? `\n  Prometheus emmett_* metrics: ${emmett.join(', ')}`
      : '\n  Prometheus: no emmett_* metrics found yet',
  );
}
async function diagnoseLoki() {
  const labels = await fetch(`${URLS.loki}/loki/api/v1/labels`)
    .then((r) => r.json() as Promise<{ data?: string[] }>)
    .catch(() => ({ data: [] as string[] }));
  console.log(`\n  Loki labels: ${(labels.data ?? []).join(', ') || '(none)'}`);
}
async function diagnoseDockerLogs(service: string, lines = 10) {
  const { stdout } = await execa('docker', [
    ...COMPOSE,
    'logs',
    '--tail',
    String(lines),
    service,
  ]).catch(() => ({ stdout: '(could not get logs)' }));
  console.log(`\n  docker logs ${service} (last ${lines}):\n  ${stdout.split('\n').join('\n  ')}`);
}

Are they pretty? No. Can they be improved? Yes. Do they have to be improved at this specific moment? No.

The setup uses test infrastructure

const CLEANUP = process.env['CLEANUP'] === '1' || process.env['CLEANUP'] === 'true';
const CLEANUP_AFTER = process.env['CLEANUP_AFTER'] === '1' || process.env['CLEANUP_AFTER'] === 'true';
const NO_START = process.env['NO_START'] === '1' || process.env['NO_START'] === 'true';
// ─── configuration ───────────────────────────────────────────────────────────
const COMPOSE = ['compose', '-f', 'docker-compose.yml', '--profile', 'observability'];
const URLS = {
  app: 'http://localhost:3000',
  prometheus: 'http://localhost:9090',
  tempo: 'http://localhost:3200',
  loki: 'http://localhost:3100',
  grafana: 'http://localhost:3001',
  otelCollectorMetrics: 'http://localhost:8889/metrics',
};
// Fresh client per run — avoids stale cart state from previous runs.
const SERVICE_NAME = 'expressjs-with-postgresql';
const CLIENT_ID = randomUUID();
const CART_ENDPOINT = `${URLS.app}/clients/${CLIENT_ID}/shopping-carts/current/product-items`;
const CONFIRM_ENDPOINT = `${URLS.app}/clients/${CLIENT_ID}/shopping-carts/current/confirm`;
// Matches the .http file — unitPrice is resolved server-side.
const ADD_PRODUCT_BODY = JSON.stringify({ productId: randomUUID(), quantity: 10 });

before(async () => {
  console.log(`\n▶ client ID for this run: ${CLIENT_ID}\n`);
  if (NO_START) {
    console.log('▶ --no-start: skipping docker compose and app startup');
    return;
  }
  if (CLEANUP) {
    console.log('▶ --cleanup: killing port 3000 and tearing down stack (down -v)…');
    await execa('bash', ['-c', 'fuser -k 3000/tcp 2>/dev/null || true']).catch(() => {});
    await new Promise((r) => setTimeout(r, 500));
    await execa('docker', [...COMPOSE, 'down', '-v', '--remove-orphans'], {
      stdio: 'inherit',
    });
  }
  const stackReady = await fetch(`${URLS.prometheus}/-/ready`)
    .then((r) => r.ok)
    .catch(() => false);
  if (stackReady) {
    console.log('▶ observability stack already up — skipping docker compose up');
  } else {
    console.log('▶ starting observability stack…');
    await execa('docker', [...COMPOSE, 'up', '-d'], { stdio: 'inherit' });
  }
  console.log('▶ waiting for backends…');
  await waitFor(() => checkUrl('Prometheus', `${URLS.prometheus}/-/ready`), {
    timeout: 90_000, label: 'Prometheus',
  });
  await waitFor(() => checkUrl('Grafana', `${URLS.grafana}/api/health`), {
    timeout: 90_000, label: 'Grafana',
  });
  await waitFor(() => checkUrl('Tempo', `${URLS.tempo}/ready`), {
    timeout: 90_000, label: 'Tempo',
  });
  await waitFor(() => checkUrl('Loki', `${URLS.loki}/ready`), {
    timeout: 90_000, label: 'Loki',
  });
  // /health returns { status: 'ok', service: 'expressjs-with-postgresql' } —
  // checking service name lets us distinguish our app from other processes on :3000.
  const checkOurApp = () =>
    checkUrl('app /health', `${URLS.app}/health`, async (res) => {
      const json = (await res.json().catch(() => ({}))) as { service?: string };
      if (json.service !== SERVICE_NAME) {
        console.log(
          `    app /health: service="${json.service ?? '(missing)'}", expected="${SERVICE_NAME}"`,
        );
        return false;
      }
      return true;
    });
  const appIsOurs = stackReady && (await checkOurApp());
  if (appIsOurs) {
    console.log('▶ app already running and healthy — skipping npm start');
  } else {
    const portTaken = await fetch(URLS.app).then(() => true).catch(() => false);
    if (portTaken) {
      // Port is occupied but not by our app — stale process or unrelated service.
      console.error(
        '\n  ✗ Port 3000 is occupied by a process that is not this app.\n' +
          '  It may be a stale version of this app (connected to a wiped database)\n' +
          '  or a completely different service.\n' +
          '  Fix: run  npm run verify:observability:cleanup  to kill it and restart,\n' +
          '  or manually free port 3000.\n',
      );
      process.exit(1);
    }
    console.log('▶ starting app…');
    app = execa('npm', ['start'], { stdio: 'inherit' });
    await waitFor(checkOurApp, { timeout: 60_000, label: 'app /health' });
  }
  console.log('▶ setup complete\n');
});

As you see, nothing fancy, the cleanup is even simpler

after(async () => {
  if (app) {
    console.log('\n▶ stopping app…');
    app.kill('SIGTERM');
    await app.catch(() => {});
    console.log('▶ app stopped');
  }
  if (CLEANUP_AFTER) {
    console.log('▶ tearing down stack (down -v)…');
    await execa('docker', [...COMPOSE, 'down', '-v', '--remove-orphans'], {
      stdio: 'inherit',
    });
    console.log('▶ stack torn down');
  } else {
    console.log('▶ stack is still running');
    console.log('▶ to clean up: npm run verify:observability:cleanup');
  }
});

Having that we can run tests:

test('successful command returns x-trace-id header', async () => {
  const res = await fetchWithDiag('POST add product', CART_ENDPOINT, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: ADD_PRODUCT_BODY,
  });
  assert.equal(res.status, 204, `Expected 204 — body logged above`);
  const header = res.headers.get('x-trace-id');
  if (!header) {
    console.error(
      '  ✗ x-trace-id missing — verify the wrapper app in src/index.ts ' +
        'adds it via @opentelemetry/api before mounting the emmett app',
    );
  }
  assert.ok(header, 'x-trace-id header missing');
  assert.match(header, /^[0-9a-f]{32}$/, `"${header}" is not a 32-hex trace ID`);
  traceId = header;
  console.log(`  trace ID: ${traceId}`);
});
test('OTel collector exposes Emmett metrics on port 8889', async () => {
  // Send a few more requests so metrics are definitely recorded.
  for (let i = 0; i < 5; i++) {
    await fetch(CART_ENDPOINT, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: ADD_PRODUCT_BODY,
    });
  }
  try {
    await waitFor(
      async () => {
        let text: string;
        try {
          const res = await fetch(URLS.otelCollectorMetrics);
          text = await res.text();
        } catch {
          console.log('    collector :8889: connection refused');
          return false;
        }
        const emmettLines = text.split('\n').filter((l) => l.startsWith('emmett_') && !l.startsWith('#'));
        if (emmettLines.length === 0) {
          const allFamilies = [...new Set(text.split('\n').filter((l) => !l.startsWith('#') && l).map((l) => l.split('{')[0]))].slice(0, 5);
          console.log(`    collector :8889: no emmett_* metrics yet. Present: ${allFamilies.join(', ') || '(none)'}`);
          return false;
        }
        return true;
      },
      { timeout: 90_000, interval: 5_000, label: 'emmett metrics on collector :8889' },
    );
  } catch (err) {
    await diagnoseCollector();
    await diagnoseDockerLogs('otel-collector');
    throw err;
  }
});

I put it into a single file that can be run as a regular Node.js script.

It already showed me (and Claude) that what they initially did wasn’t working if you try to run it multiple times. It also showed that doing a full cleanup and rebuild, and making it reproducible, needs more work.

Is it done? Not yet; it takes too much time and resources to run it continuously throughout the pipeline. The code is a bit messy, so it needs to be organised. It’s segmented into blocks, includes basic automation and tests, and has already gone through some failures to get it done.

Could I do it better? Sure, and I will improve it, but that’s not the point. I wanted to show you my findings during weekend vibing (without beer tho), the real, not polished iteration, before I run the next one.

The main idea behind OODA loops is not to be perfect, but to iterate quickly, gather feedback as soon as possible, learn from it, develop another theory, and verify it through action.

It’s not about vibing, but it’s also not about analysis paralysis.

I hope you’re now better equipped to think about when vibing — with beer or without, with LLMs or without — actually helps, and when it doesn’t.

Vibe coding is just high-frequency steering. It only works if you have a Harness: a mechanical way to observe and orient, so you don’t steer the whole project into a wall.

Act takes seconds now. Observe takes as long as it always did. Without a harness, you’re not going faster; you’re just making more stuff you haven’t checked.

Harness is not magic, a new discipline, or the next buzzword; I hope I showed you that a bit in this article on what it may look like.

So iterate fast, but wisely remembering to do the full loop. It’s great that LLMs can help us make Acting faster, but we should not skip other steps. We should aim for a fast feedback loop to iterate in the right direction and achieve continuous improvement, to deliver proper value.

Just like Vibing isn’t new, we shouldn’t abandon old engineering practices. We should also not replace collaboration with solitary self-high fives.

Check also:

  • Emmett Pull Request with mentioned changes
  • Interactive Rubber Ducking with GenAI
  • The End of Coding? Wrong Question
  • A few tricks on how to set up related Docker images with docker-compose
  • Docker Compose Profiles, one the most useful and underrated features

Cheers!

Oskar

cfmlFiddle - Compare ColdFusion, Lucee, and BoxLang Side-by-Side

Mike's Notes

Thank you, James. This will help with code testing.

Resources

References

  • Reference

Repository

  • Home > Ajabbi Research > Library >
  • Home > Handbook > 

Last Updated

23/04/2026

cfmlFiddle - Compare ColdFusion, Lucee, and BoxLang Side-by-Side

By: James Moberg
myCFML: 16/04/2026

Mike is the inventor and architect of Pipi and the founder of Ajabbi.

I built a local CFML playground that runs 10 engines at once

I've been writing CFML for a long time. Long enough to remember when testing something meant editing a file, refreshing the browser, and hoping the server hadn't crashed. We have better tools now, but I kept running into the same problem: I'd want to check how something behaves on CF2021 vs CF2025, or whether Lucee handles a date function differently than Adobe, and there wasn't a good way to do that without maintaining a bunch of separate installs.

The online tools help. CFFiddle.org, TryCF.com, and Try BoxLang are all useful when you need a quick test. But I kept hitting limitations. CFFiddle requires a social login to use some features. TryCF doesn't indicate which patch version it's running against. Neither lets you compare engines side-by-side. And both go offline sometimes, usually right when I need them. :(

So I built cfmlFiddle.

What it is

cfmlFiddle is a self-hosted CFML playground. It runs on your machine through CommandBox. You write code in an Ace Editor, pick an engine (or all of them), click Run, and see the output. If you picked multiple engines, you see all the results stacked, side by side, or tabbed.

cfmlFiddle screenshot

The default config ships with 10 server definitions:

  • Adobe ColdFusion 2016, 2021, 2023, 2025
  • Lucee 5, 6, 7
  • BoxLang (native, Adobe compat, Lucee compat)

You start whichever ones you need. Most of the time I run two or three.

The part I actually wanted

My main gripe with the online tools was never being able to pin a version. If I'm debugging something a client reported on CF2021.0.14, I need to know what CF2021.0.14 does, not whatever patch the hosted service happens to be running this week.

With cfmlFiddle, each engine version is a CommandBox server.json file. You control which version is installed, down to the patch. You can keep CF2021.0.14 around for months if you need it, or install CF2025 the day it drops.

The other thing: running code that the hosted services block. File operations, HTTP calls, Java objects, custom tags. cfmlFiddle doesn't restrict anything. It's your machine.

How the comparison works

Click "Run All Online" and cfmlFiddle sends your code to every running engine simultaneously via cfhttp. Each engine executes the same temp file from a shared webroot. The results come back with timing info, the engine name, and the actual patch version, so you can see exactly what ran where.

There's also an "Append" mode. Check the box and each run stacks on top of the previous results, so you can tweak your code and compare iterations without losing the earlier output.

Interactive mode

I wrote a test script with a <form> and immediately realized the form couldn't post back to itself. The result was static HTML in a div. The form action had nowhere to go.

cfmlFiddle now auto-detects forms in your output. When it finds one (or you check the Interactive box), it renders the result in a sandboxed iframe pointing directly at the payload file on the target engine. The form posts back to itself, processes the data, and returns the result. Multi-step scripts just work.

Under the hood

The status bar uses Server-Sent Events instead of polling. The heartbeat checks all engines with raw TCP socket connections (~50ms total for 10 servers) and streams updates to the browser in real time. It falls back to polling if SSE doesn't work on a particular engine.

Config lives in a JSON file above the webroot. You can change settings without editing CFML code.

All the frontend libraries (Ace, jQuery, SweetAlert2, jQuery contextMenu) ship locally in an assets/vendor/ directory. No CDN dependency by default, though you can flip a config switch if you prefer CDN.

Server management is built into the UI. Click the status bar to start, stop, or inspect engines. Left-click any server for a context menu with direct links to its admin panel, homepage, and documentation.

Session management

Every time you run code, cfmlFiddle saves the payload file with a timestamp. Click the Session button in the toolbar to see a list of everything you've run. Click any entry to reload it into the editor. When you're done, Archive All zips everything up and clears the working directory.

I kept losing track of what I'd tested ten minutes ago. Now I just open the session list and pick it.

The smaller stuff

There's a light/dark theme toggle. It picks up your OS preference by default, and the Ace editor switches to match. I bounce between light and dark depending on the time of day, so this was mostly for me.

You can import code from a GitHub Gist URL. Paste the link, it pulls the first file and drops it in the editor. Useful when someone shares a snippet and you want to see what it does on three engines before replying.

Snippets work the other direction too. Save whatever's in the editor as a named file, reload it later from the dropdown.

Each result card has a refresh button that re-executes and updates the timing, plus a dismiss button to toss results you don't need. Small thing, but it adds up when you're iterating.

We also put some work into keyboard accessibility: skip link, visible focus indicators, arrow keys on the splitter, ARIA roles on the toolbar and status bar.

Getting it

cfmlFiddle is open source under the MIT license.

Website: cfmlFiddle.com Source: GitHub

You need CommandBox installed. Clone the repo, edit config.json with your box.exe path, run box task run launchCFMLFiddle, and pick an engine. It opens in your browser.

cfmlFiddle is a myCFML.com project, sponsored by SunStar Media.

Tony Hoare introduced Communicating Sequential Processes (CSP)

Mike's Notes

Alex introduced me to Tony Hoare.

"As far as I remember, the main focus of messaging is on exchange protocols—a whole separate field of algorithmic analysis of interacting processes. Hoare wrote a treatise on this back in the last century, "Interacting Sequential Processes"—I think that's what it's called." - Alex Shkotin

Resources

References

  • Learning CSP, by Tony Hoare
  • Communicating Sequential Processes by Tony Hoare, ACM

Repository

  • Home > Ajabbi Research > Library >
  • Home > Handbook > 

Last Updated

31/01/2026

Tony Hoare introduced Communicating Sequential Processes (CSP)

By: 
Stanford: Copied 31/01/2026

Sir Charles Antony Richard Hoare (/hɔːr/ HOR; born 11 January 1934), also known as C. A. R. Hoare, is a British computer scientist who has made foundational contributions to programming languages, algorithms, operating systems, formal verification, and concurrent computing.[3] His work earned him the 1980 ACM Turing Award, usually regarded as the highest distinction in computer science.


 

Tony Hoare, winner of the Association for Computing Machinery's A.M. Turing Award, discusses the origin of his model of "Communicating Sequential Processes" and the central importance of keeping processes from directly accessing the state information of other processes. This clip taken from an interview conducted with Hoare by Cliff Jones for the ACM on November 24. 2015. Video of the full interview is available as part of Hoare’s ACM profile at https://amturing.acm.org/award_winners/hoare_4622167.cfm


On Design

"There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies." - Tony Hoare

Introduction

Tony Hoare introduced Communicating Sequential Processes (CSP) in 1978 as a language to describe interactions between concurrent processes. Historically, software advancement has mainly relied upon improvements in hardware that create enable faster CPUs and larger memory. Hoare recognized that a machine with hardware that is 10 times as fast running a code that consumes 10 times more resources is not an improvement.

While concurrency has many advantages over traditional sequential programming, it has failed to gain a popular audience because of its erroneous nature. With CSP, Hoare introduced a precise theory that can mathematically guarantee programs to be free of the common problems of concurrency. In his book, Learning CSP (the third most quoted book in Computer Science), Hoare uses calculus to show that it is possible to work with deadlocks and nondeterminism as if they were terminal events in ordinary processes. By reducing the errors of CSP, Hoare has enabled computer scientists to fully exploit the capacity of CPUs.

What is concurrency?

The ordinary task of doing your laundry illustrates the basics of concurrency. There are two ways to finish two loads of laundry:

  1. Put 1st load in washing machine → put 1st load in dryer → fold 1st load → put the 2nd load into the washing machine → repeat process.
  2. Put 1st load in washing machine → put 1st load in dryer → put 2nd load in washing machine → etc…

Clearly, the second method is quicker and better utilizes resources. If the first load is in the dryer, the washing machine isn’t being used and should be used by the second load. This is the basics of concurrency.

Historical Information

The earliest ideas for concurrent processing arose naturally in the 1960’s because of scarce resources. At that time, processing power was expensive, and it was wasteful for a processor to have to wait while it communicated with slow peripheral equipment or human (Hoare, Learning CSP).

Ex: The task of performing a simple addition problem shows how concurrency can greatly improve computational efficiency. Adding numbers requires three parts:

  1. Ask user for input numbers
  2. Performing calculation
  3. Printing the answer

Problems of concurrency and Hoare’s solution

While concurrency offers great potential for faster computation, it is not without fault. Unlike parallelism, where n tasks run on n processors, in concurrency, n tasks run on 1 processor. Because the amount of resources doesn’t increase, programs that need to use the same resource must wait.

  1. The amount of time user waits increases linearly
  2. The amount of storage space needed increases with number of jobs
  3. Difficulty verifying program correctness

The difficulty of verifying program correctness has been the primary hindrance in the field. Programmers have shied away from parallel programming because errors that arise in this method of programming are notoriously difficult to track down. Programs are often prone to errors that not obvious and surface under arbitrary and unrepeatable situations. The complex nature of concurrency leaves the programmer in doubt. Programmers often resort to exhaustive search tactics to find errors:

Testing the code rigorously to sort out obvious concurrency issues and hoping that all problems have been resolved

Completely follow design patterns and guidelines for concurrent programming. This method is limited in its applicability.

OR...

Hoare’s approach CSP uses mathematical deductions to prove that a program is error free. Through the application of CSP, programmers no longer search for bugs in written programs, but rather can write programs that are logically guaranteed to be correct.

General terms in CSP

Alphabet- set of events which are considered relevant for a particular object. The alphabet of a process is enclosed within curly brackets. a. ex: vending machine- alphabet {coin, chocolate} b. not valid: {coin, car} Trace: sequence of symbols recording the events in which the process has engaged in within a given time. The trace is enclosed within angle brackets. c. Vending machine:

Nondeterminism

In a concurrent program, two or more processes compete for the same resource. The resolution of this dilemma is not always deterministic. The unpredictable arrival order of messages creates a nondeterministic state (2).

Ex: A change machine can give change for a dollar in many different ways: four quarters, ten dimes, 100 pennies. The type of change given is not dependent on the type of change machine, but rather by some arbitrary or nondeterministic fashion.

Ex2: A passenger waiting for the bus to take him to London. The A, B, D, and F lines all go to London. The passenger can take any f these lines. Which line he gets on is only dependent upon which bus arrives first.

Why nondeterminism? Programmers use nondeterminism to exclude the events that don’t effect the outcome as a technique to simplify the problem. In the case of the change machine, only the sum, not the combination of coins matters. By reducing the number of variables, nondeterminism helps maintain a high level of abstraction when describing complicated systems.

Problems with nondeterminism Although nondeterminism can greatly reduce the complexity of problems, they also introduce their other issues. In a deterministic program, the answer will always be the same given the same inputs. In a nondeterministic program, the same inputs can yield different answers on different cycles or machines. This characteristic makes it difficult to check whether the program works.

CSP and nondeterminism

CSP introduces the notation Ξ  to signify a process which “behaves either like P or like Q, where the selection between them is arbitrarily, without the knowledge of the external environment (1).”

Ex: During lunch, you can choose between an apple or an orange. The choice can be mathematically expressed as: orange Ξ  apple, where the choice between the two is based on a unaccounted external factor.

Algebraic laws governing nondeterministic choices are simple.

  • Idempotenence: A choice between P and P is empty P Ξ  Q = P
  • Symmetry: P Ξ  Q= Q Ξ  P The order does not influence the choice
  • Associative: P Ξ  (Q Ξ  R) = (P Ξ  Q) Ξ  R The choice between three options can be divided into two successive single choices.
  • Distributive: x → (P Ξ  Q) = (x → P) Ξ  (x → Q) Going from a defined path x to a choice between path P and Q, is the same as choosing between the options of going from path x to P or from path x to Q.

Fairness

In some theories, nondeterminism is obliged to be fair, in the sense that an event that infinitely often may happen eventually must happen (though there is no limit to how long it may be delayed). In Hoare’s theory, the concept of fairness doesn’t exist:

“Because we observe only finite traces of the behaviour of a process, if an event can be postponed indefinitely, we can never tell whether it is going to happen or not. If we want to insist that the event shall happen eventually, we must state that there is a number n such that every trace longer than n contains that event. Then the process must be designed explicitly to satisfy this constraint. For example, in the process P0 defined below, then event a must always occur within n steps of its previous occurrence.”

-Learning CSP

If fairness is required for the program, it must be considered and accounted for separately.

Shared Resources

Laws for reasoning about sequential processes derives from the fact that each variable is updated by one process (learning CSP). If storage is shared, only one process can change the variable. The potential for data corruption makes common variables and communication amongst processes difficult to implement.

Deadlock

Deadlock is the permanent blocking of a set of processes. It is a common problem in concurrency and arises from the conflicting needs of processes for similar resources or when communicating with each other.

Example of deadlock: Intersection of cars(3). The shared resources can be thought of as the lanes. Each car shares the four lanes. The process is the car. Deadlock occurs when each process holds one resource and requests the other. While one car can decide to switch lanes, no car can agree on the proper action to take. As in traffic, deadlock in computer science slows or completely halts a program.

Classical illustration of deadlock

There is a group of five philosophers who do nothing but eat and think all day. The philosophers sit around a round table with a bowl of noodles in the middle. As philosophers get paid less than computer scientists, they can afford only five single chopsticks, which are placed on each side of the philosopher. To eat the noodle, the philosopher needs both chopsticks. The philosopher first picks up the chopstick from his left, and then his right if it is not being used.

Deadlock arrives when all philosophers want to eat at exactly the same time. All philosophers pick up the chopstick to their left. However, none of the philosophers can eat because another philosopher is currently using the other chopstick.

Events that lead to Deadlock

There are several combinations of events can cause deadlock

  1. Mutual exclusion: Only one process can use a resource at a time
  2. Hold- and- wait: A process holds onto its resource until the next resource its needs becomes available
  3. No preemption: No process can be forced to give up its resources
  4. Circular wait: closed chain of processes where each process holds the resource the next process needs to function.

While these situations can lead to deadlock, there are precautions programmers can take to prevent their occurrence.

  1. Mutual exclusion: Restrict the way in which resources can be requested.
  2. Hold- and- wait: Require all processes to provide information about the resources they will need in advance. Use algorithms to insure that all resources are available to the process before it attempts to acquire them.
  3. Circular wait: Establish a priority system that requires processes to request resources and process them in that order, such that a higher priority process will always have access to the resource first. This solution can lead to starvation.

Eliminating the possibility of a deadlock is better than dealing the deadlock during execution. However there will may arise arrive unique combination of situations that lead to deadlock. There are methods of resolving a deadlock when it’s detected, but these solutions are not efficient and resolve in lost data (4).

  1. Preempt the resource from a process. The preempt process can be resumed at a later time.
  2. Return to a point where the process did not need the acquired resource causing the deadlock.
  3. Systematic killing of jobs until deadlock is resolved.

CSP and deadlock solution

In order to prevent data corruption, Hoare purposed the concept of a critical area. Processes cross the critical area to gain access to the shared data. Before entry to the critical area, all other processes must verify and update the value of the shared variable. Upon exit, the processes must again verify that all processes have the same value.

Another technique to maintain data integrity is through the use of mutual exclusion semaphore or a mutex. A mutex is a specific subclass of a semaphore that only allows one process to access the variable at once. A semaphore is a restricted access variable that serves as the classic solution to preventing race hazards in concurrency. Other processes attempting to access the mutex are blocked and must wait until the current process releases the mutex. When the mutex is released, only one of the waiting processes will gain access to the variable, and all others continue to wait.

In the early 1970s, Hoare developed a concept known as a monitor based on the concept of the mutex. According to a tutorial on CSP in the Java programming language written by IBM:

“A monitor is a body of code whose access is guarded by a mutex. Any process wishing to execute this code must acquire the associated mutex at the top of the code block and release it at the bottom. Because only one thread can own a mutex at a given time, this effectively ensures that only the owing thread can execute a monitor block of code.”

Monitors can help prevent data corruption and deadlocks (5)

Possible Solutions to Philosopher Problem

A physical representation of the solution to the deadlock problem can be visualized as the footman. The behavior of the footman allows him to sit only four philosophers at the table simultaneously.

The metaphor of the dining philosophers was thought by the well known computer scientist, Edsger Dijkstra. Carel S. Scholten discovered the footman solution.

Infinite Overtaking

This problem arises when priority is assigned to programs. Some program always takes precedence at the expense of other programs that are delayed forever.

Ex: You are waiting to be seated at a restaurant. You are next in line, and just about to be shown your table when a famous actor walks in. The restaurant, mindful of good publicity, seats the famous actor first. When the next table becomes available, the waiter turns to you, but then sees a famous singer walk in. Again, the waiter seats the singer before you. The weighting of resources leaves you at a disadvantage. If this cycle continues, you could be delayed forever, or at least for an unacceptable period of time.

Overtaking Solution

The task of deciding how to allocate resources to waiting processes is called scheduling. Scheduling is split into two events, which Hoare terms the please and the thankyou:

  1. Please- processes requesting the resource
  2. Thankyou- the allocation of the resource to processes.

The time between the request and granting of the resource is the waiting period. In CSP, there are several techniques that prevent infinite waiting times.

  1. Limiting resource use and increasing availability of resource.
  2. First in first out (FIFO)- allocate resource to the process that has waited the longest.
  3. Bakery algorithm (A more technical explanation of the scheduling algorithm can be found in the reference (6))

Limitations of CSP

In determininistic programs, the result will be the same if the environment is constant. Because concurrency is based on non-determinisim, the environment does not affect the program. Given the paths chosen, the program can run several times and receive different result. To insure the accuracy of concurrent programs, programmers must be able to consider the execution of their program on a holistic level.

However, despite the formal methods that Hoare introduced, there still lacks any proof method to verify correct programs. CSP can only catch problems it knows exists, not unknown problems. While commercial applications based on CSP, such as ConAn, can detect the presence of errors, it can’t detect their absence. While CSP gives you the tools to write a program that can avoid the common concurrency errors, the proof of a correct program remains an unresolved area in CSP.

Future of CSP

CSP has great potential in biology and chemistry to model complex systems in nature. It has not been widely used in industry because of the many existing logical problems facing the industry. At the conference for the 25th anniversary for the development of CSP, Hoare noted that despite the many research projects funded by Microsoft, Bill Gates ignores the issue of when Microsoft will be able to commercialize the work on CSP (7).

Hoare reminds his audience that the area of dynamic procedures still requires much more research. Currently, the computer science community is stuck in the paradigm of sequential thought. With the foundation in formal methods of concurrency established by Hoare, the scientific community is primed to being the next revolution in parallel programming.

References

  1. Hoare, C.A.R. Learning CSP. June 21, 2004.
  2. Haghighi, Hassan and Mirian-Hosseinabadi, Seyyed H. Nondeterminism in Formal Development of Concurrent Programs: A Constructive Approach
  3. Concurrency: Deadlock and Starvation. Presentation Obtained from engr.smu.edu/~kocan/7343/fall05/slides/Chapter06.ppt
  4. Rinard, Martin C. Operating Systems Lecture Notes
  5. Abhijit Belapurkar. CSP for Java Programmers, Part 1
  6. Carnegie Melon. Bakery Algorithm
  7. Numerico, Teresa an Bowen, Jonathon. 25 Years of CSP